@zenfg/inspector 0.1.0-beta.3 → 0.1.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/GUIDE.md +182 -0
- package/README.md +61 -89
- package/THEMING.md +124 -0
- package/dist/FrameGraphInspector.d.ts +23 -4
- package/dist/FrameGraphInspector.d.ts.map +1 -1
- package/dist/FrameGraphInspector.js +137 -29
- package/dist/FrameGraphInspector.js.map +1 -1
- package/dist/capture.d.ts +5 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +2 -0
- package/dist/capture.js.map +1 -0
- package/dist/debugCaptureModel.d.ts +19 -0
- package/dist/debugCaptureModel.d.ts.map +1 -1
- package/dist/debugCaptureModel.js +36 -2
- package/dist/debugCaptureModel.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/panelAliasAnalysis.d.ts +1 -0
- package/dist/panelAliasAnalysis.d.ts.map +1 -1
- package/dist/panelAliasAnalysis.js +23 -54
- package/dist/panelAliasAnalysis.js.map +1 -1
- package/dist/panelCytoscapeGraphRenderer.d.ts +15 -2
- package/dist/panelCytoscapeGraphRenderer.d.ts.map +1 -1
- package/dist/panelCytoscapeGraphRenderer.js +145 -23
- package/dist/panelCytoscapeGraphRenderer.js.map +1 -1
- package/dist/panelDetailLayout.d.ts +27 -0
- package/dist/panelDetailLayout.d.ts.map +1 -0
- package/dist/panelDetailLayout.js +174 -0
- package/dist/panelDetailLayout.js.map +1 -0
- package/dist/panelDetailStyles.d.ts +2 -0
- package/dist/panelDetailStyles.d.ts.map +1 -0
- package/dist/panelDetailStyles.js +57 -0
- package/dist/panelDetailStyles.js.map +1 -0
- package/dist/panelDiagnosticsView.d.ts +10 -1
- package/dist/panelDiagnosticsView.d.ts.map +1 -1
- package/dist/panelDiagnosticsView.js +166 -57
- package/dist/panelDiagnosticsView.js.map +1 -1
- package/dist/panelDomHelpers.d.ts.map +1 -1
- package/dist/panelDomHelpers.js +6 -5
- package/dist/panelDomHelpers.js.map +1 -1
- package/dist/panelGraphLayout.d.ts +3 -2
- package/dist/panelGraphLayout.d.ts.map +1 -1
- package/dist/panelGraphLayout.js +6 -5
- package/dist/panelGraphLayout.js.map +1 -1
- package/dist/panelGraphRenderer.d.ts +10 -0
- package/dist/panelGraphRenderer.d.ts.map +1 -1
- package/dist/panelGraphRenderer.js.map +1 -1
- package/dist/panelGraphScene.d.ts +1 -0
- package/dist/panelGraphScene.d.ts.map +1 -1
- package/dist/panelGraphScene.js +69 -32
- package/dist/panelGraphScene.js.map +1 -1
- package/dist/panelGraphSearch.d.ts +16 -0
- package/dist/panelGraphSearch.d.ts.map +1 -0
- package/dist/panelGraphSearch.js +93 -0
- package/dist/panelGraphSearch.js.map +1 -0
- package/dist/panelGraphView.d.ts +82 -0
- package/dist/panelGraphView.d.ts.map +1 -1
- package/dist/panelGraphView.js +15 -4
- package/dist/panelGraphView.js.map +1 -1
- package/dist/panelGraphVisuals.d.ts +14 -6
- package/dist/panelGraphVisuals.d.ts.map +1 -1
- package/dist/panelGraphVisuals.js +126 -51
- package/dist/panelGraphVisuals.js.map +1 -1
- package/dist/panelInspectorView.d.ts +8 -0
- package/dist/panelInspectorView.d.ts.map +1 -1
- package/dist/panelInspectorView.js +242 -48
- package/dist/panelInspectorView.js.map +1 -1
- package/dist/panelListStyles.d.ts +3 -0
- package/dist/panelListStyles.d.ts.map +1 -0
- package/dist/panelListStyles.js +155 -0
- package/dist/panelListStyles.js.map +1 -0
- package/dist/panelMemoryStyles.d.ts +3 -0
- package/dist/panelMemoryStyles.d.ts.map +1 -0
- package/dist/panelMemoryStyles.js +42 -0
- package/dist/panelMemoryStyles.js.map +1 -0
- package/dist/panelMemoryView.d.ts +13 -1
- package/dist/panelMemoryView.d.ts.map +1 -1
- package/dist/panelMemoryView.js +161 -41
- package/dist/panelMemoryView.js.map +1 -1
- package/dist/panelPassesView.d.ts +15 -0
- package/dist/panelPassesView.d.ts.map +1 -1
- package/dist/panelPassesView.js +202 -72
- package/dist/panelPassesView.js.map +1 -1
- package/dist/panelRawView.d.ts +15 -0
- package/dist/panelRawView.d.ts.map +1 -0
- package/dist/panelRawView.js +105 -0
- package/dist/panelRawView.js.map +1 -0
- package/dist/panelResourcesView.d.ts +8 -0
- package/dist/panelResourcesView.d.ts.map +1 -1
- package/dist/panelResourcesView.js +62 -31
- package/dist/panelResourcesView.js.map +1 -1
- package/dist/panelSelection.d.ts +9 -1
- package/dist/panelSelection.d.ts.map +1 -1
- package/dist/panelSelection.js +34 -4
- package/dist/panelSelection.js.map +1 -1
- package/dist/panelTheme.d.ts +13 -0
- package/dist/panelTheme.d.ts.map +1 -0
- package/dist/panelTheme.js +104 -0
- package/dist/panelTheme.js.map +1 -0
- package/dist/panelTypes.d.ts +10 -1
- package/dist/panelTypes.d.ts.map +1 -1
- package/dist/panelTypes.js.map +1 -1
- package/dist/panelVisualTheme.d.ts +147 -50
- package/dist/panelVisualTheme.d.ts.map +1 -1
- package/dist/panelVisualTheme.js +34 -44
- package/dist/panelVisualTheme.js.map +1 -1
- package/dist/panelWorkbenchHelpers.d.ts +12 -1
- package/dist/panelWorkbenchHelpers.d.ts.map +1 -1
- package/dist/panelWorkbenchHelpers.js +62 -1
- package/dist/panelWorkbenchHelpers.js.map +1 -1
- package/dist/panelWorkbenchStyles.d.ts +2 -0
- package/dist/panelWorkbenchStyles.d.ts.map +1 -0
- package/dist/panelWorkbenchStyles.js +101 -0
- package/dist/panelWorkbenchStyles.js.map +1 -0
- package/dist/panelWorkbenchView.d.ts +16 -0
- package/dist/panelWorkbenchView.d.ts.map +1 -1
- package/dist/panelWorkbenchView.js +228 -50
- package/dist/panelWorkbenchView.js.map +1 -1
- package/dist/query.js.map +1 -1
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +147 -195
- package/dist/styles.js.map +1 -1
- package/dist/theme.d.ts +22 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +10 -0
- package/dist/theme.js.map +1 -0
- package/dist/themeDefinitions.d.ts +251 -0
- package/dist/themeDefinitions.d.ts.map +1 -0
- package/dist/themeDefinitions.js +96 -0
- package/dist/themeDefinitions.js.map +1 -0
- package/dist/themePalette.d.ts +66 -0
- package/dist/themePalette.d.ts.map +1 -0
- package/dist/themePalette.js +37 -0
- package/dist/themePalette.js.map +1 -0
- package/dist/themes.css +165 -0
- package/package.json +44 -10
- package/src/FrameGraphInspector.ts +130 -31
- package/src/capture.ts +4 -0
- package/src/debugCaptureModel.ts +53 -2
- package/src/index.ts +6 -2
- package/src/panelAliasAnalysis.ts +24 -70
- package/src/panelCytoscapeGraphRenderer.ts +140 -23
- package/src/panelDetailLayout.ts +155 -0
- package/src/panelDetailStyles.ts +56 -0
- package/src/panelDiagnosticsView.ts +166 -85
- package/src/panelDomHelpers.ts +4 -5
- package/src/panelGraphLayout.ts +6 -5
- package/src/panelGraphRenderer.ts +7 -0
- package/src/panelGraphScene.ts +68 -30
- package/src/panelGraphSearch.ts +96 -0
- package/src/panelGraphView.ts +14 -4
- package/src/panelGraphVisuals.ts +122 -52
- package/src/panelInspectorView.ts +227 -48
- package/src/panelListStyles.ts +154 -0
- package/src/panelMemoryStyles.ts +41 -0
- package/src/panelMemoryView.ts +178 -53
- package/src/panelPassesView.ts +190 -137
- package/src/panelRawView.ts +99 -0
- package/src/panelResourcesView.ts +69 -56
- package/src/panelSelection.ts +37 -5
- package/src/panelTheme.ts +85 -0
- package/src/panelTypes.ts +7 -1
- package/src/panelVisualTheme.ts +38 -49
- package/src/panelWorkbenchHelpers.ts +60 -2
- package/src/panelWorkbenchStyles.ts +100 -0
- package/src/panelWorkbenchView.ts +201 -52
- package/src/query.ts +11 -11
- package/src/styles.ts +148 -195
- package/src/theme.ts +24 -0
- package/src/themeDefinitions.ts +103 -0
- package/src/themePalette.ts +44 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { InspectorThemeController, resolveGraphTheme } from "./panelTheme.js";
|
|
1
2
|
import { FrameGraphSnapshotValidationError, decodeFrameGraphSnapshot, parseFrameGraphSnapshot, stringifyFrameGraphSnapshot, } from '@zenfg/snapshot';
|
|
2
3
|
import { createDebugViewModel, } from "./debugCaptureModel.js";
|
|
3
4
|
import { createToolbarButton } from "./panelDomHelpers.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { selectionExists } from "./panelSelection.js";
|
|
5
|
+
import { destroyGraph, fitGraph, resolveGraphScene, renderGraphLegend, } from "./panelGraphView.js";
|
|
6
|
+
import { graphGroupElementId, selectionKey } from "./panelGraphScene.js";
|
|
7
|
+
import { resolveNodeSelection, selectionExists } from "./panelSelection.js";
|
|
8
8
|
import { ensureFrameGraphInspectorStyles } from "./styles.js";
|
|
9
9
|
import { sameSelection } from "./panelWorkbenchHelpers.js";
|
|
10
10
|
import { FrameGraphDebugWorkbench } from "./panelWorkbenchView.js";
|
|
@@ -30,10 +30,12 @@ const DEFAULT_BRANDING = 'ZenFG Inspector';
|
|
|
30
30
|
export class FrameGraphInspector {
|
|
31
31
|
/** Root element owned by this inspector instance. */
|
|
32
32
|
dom = document.createElement('section');
|
|
33
|
+
themeController = new InspectorThemeController(this.dom);
|
|
33
34
|
body = document.createElement('div');
|
|
34
35
|
content = document.createElement('div');
|
|
35
36
|
dropOverlay = document.createElement('div');
|
|
36
37
|
groupsButton;
|
|
38
|
+
declarationsButton;
|
|
37
39
|
collapseGroupsButton;
|
|
38
40
|
graphView;
|
|
39
41
|
workbench;
|
|
@@ -54,6 +56,7 @@ export class FrameGraphInspector {
|
|
|
54
56
|
copyFeedbackTimeout;
|
|
55
57
|
maxImportBytes;
|
|
56
58
|
dragDepth = 0;
|
|
59
|
+
revealRevision = 0;
|
|
57
60
|
handleDragEnter = (event) => {
|
|
58
61
|
if (!isFileDrag(event))
|
|
59
62
|
return;
|
|
@@ -117,8 +120,10 @@ export class FrameGraphInspector {
|
|
|
117
120
|
host: document.createElement('div'),
|
|
118
121
|
toolbar: document.createElement('div'),
|
|
119
122
|
legend: graphLegend,
|
|
123
|
+
refreshTheme: () => this.refreshTheme(),
|
|
120
124
|
layoutElementBudget: normalizeLimit(options.maxGraphElements, DEFAULT_MAX_GRAPH_ELEMENTS, 'maxGraphElements'),
|
|
121
125
|
groupsEnabled: true,
|
|
126
|
+
showResourceDeclarations: true,
|
|
122
127
|
expandedGroupPaths: new Set(),
|
|
123
128
|
fitOnNextRender: true,
|
|
124
129
|
};
|
|
@@ -126,17 +131,20 @@ export class FrameGraphInspector {
|
|
|
126
131
|
this.graphView.toolbar.className = 'zenfg-inspector-graph-toolbar';
|
|
127
132
|
this.graphView.toolbar.setAttribute('role', 'toolbar');
|
|
128
133
|
this.graphView.toolbar.setAttribute('aria-label', 'Frame graph view controls');
|
|
134
|
+
this.declarationsButton = createToolbarButton('Declarations', 'Show resource declaration nodes', () => this.toggleDeclarations());
|
|
129
135
|
this.groupsButton = createToolbarButton('Groups', 'Toggle diagnostic group projection', () => this.toggleGroups());
|
|
130
136
|
this.collapseGroupsButton = createToolbarButton('Collapse All', 'Collapse every diagnostic group', () => this.collapseAllGroups());
|
|
131
137
|
const actionControls = document.createElement('div');
|
|
132
138
|
actionControls.className = 'zenfg-inspector-graph-action-controls';
|
|
133
|
-
actionControls.append(this.groupsButton, this.collapseGroupsButton,
|
|
134
|
-
this.graphView.toolbar.append(
|
|
139
|
+
actionControls.append(this.declarationsButton, this.groupsButton, this.collapseGroupsButton, createToolbarButton('Fit', 'Fit graph to view', () => fitGraph(this.graphView)));
|
|
140
|
+
this.graphView.toolbar.append(actionControls);
|
|
135
141
|
const callbacks = {
|
|
136
142
|
onSelect: (selection) => this.handleSelect(selection),
|
|
137
143
|
onHover: (selection) => this.handleHover(selection),
|
|
138
144
|
onGroupToggle: (pathKey) => this.toggleGroup(pathKey),
|
|
139
145
|
isGroupExpanded: (pathKey) => this.graphView.expandedGroupPaths.has(pathKey),
|
|
146
|
+
onReveal: (selection, tab) => this.handleReveal(selection, tab),
|
|
147
|
+
onNavigate: (tab, filter) => this.workbench.navigate(tab, filter),
|
|
140
148
|
};
|
|
141
149
|
this.workbench = new FrameGraphDebugWorkbench(this.graphView, callbacks, {
|
|
142
150
|
onCapture: () => { void this.captureSnapshot(); },
|
|
@@ -158,20 +166,53 @@ export class FrameGraphInspector {
|
|
|
158
166
|
this.updateCaptureActions();
|
|
159
167
|
this.updateGraphControls();
|
|
160
168
|
this.showEmptyState();
|
|
161
|
-
|
|
169
|
+
if (options.theme)
|
|
170
|
+
this.setTheme(options.theme);
|
|
171
|
+
queueMicrotask(() => { if (!this.destroyed) {
|
|
172
|
+
this.refreshTheme();
|
|
173
|
+
this.maybeAutoCapture();
|
|
174
|
+
} });
|
|
175
|
+
}
|
|
176
|
+
/** Replace API-applied variables on this instance, then synchronize graph styles.
|
|
177
|
+
* Pass null to restore host CSS and defaults. Does not change capture or interaction state.
|
|
178
|
+
*/
|
|
179
|
+
setTheme(theme) {
|
|
180
|
+
if (this.destroyed)
|
|
181
|
+
return;
|
|
182
|
+
this.themeController.apply(theme);
|
|
183
|
+
this.refreshTheme();
|
|
184
|
+
}
|
|
185
|
+
/** Re-read final CSS values after external CSS changes and refresh graph and legend.
|
|
186
|
+
* Does not write theme variables, recapture, fit, or rebuild the component.
|
|
187
|
+
*/
|
|
188
|
+
refreshTheme() {
|
|
189
|
+
if (this.destroyed)
|
|
190
|
+
return;
|
|
191
|
+
const theme = resolveGraphTheme(this.dom);
|
|
192
|
+
this.graphView.theme = theme;
|
|
193
|
+
this.graphView.renderer?.setTheme?.(theme);
|
|
194
|
+
if (this.viewModel)
|
|
195
|
+
renderGraphLegend(this.graphView.legend, this.viewModel, theme, this.graphView.showResourceDeclarations);
|
|
162
196
|
}
|
|
163
197
|
/**
|
|
164
198
|
* Replaces or removes the live-capture provider.
|
|
165
199
|
*
|
|
166
200
|
* @remarks Installing a provider may immediately begin an asynchronous
|
|
167
|
-
* capture when no snapshot is displayed.
|
|
201
|
+
* capture when no snapshot is displayed. Replacing or removing a provider
|
|
202
|
+
* invalidates its pending capture results without cancelling the provider
|
|
203
|
+
* promise. An already displayed snapshot and any pending import are preserved.
|
|
168
204
|
*/
|
|
169
205
|
setCaptureSnapshotProvider(provider) {
|
|
170
|
-
|
|
206
|
+
if (this.destroyed || this.captureSnapshotCallback === provider)
|
|
207
|
+
return;
|
|
208
|
+
if (this.capturing) {
|
|
209
|
+
this.operationRevision += 1;
|
|
210
|
+
this.capturing = false;
|
|
211
|
+
}
|
|
171
212
|
this.captureSnapshotCallback = provider;
|
|
172
|
-
if (
|
|
213
|
+
if (!this.viewModel)
|
|
173
214
|
this.initialAutoCaptureAttempted = false;
|
|
174
|
-
if (!provider && !this.viewModel)
|
|
215
|
+
if (!provider && !this.viewModel && !this.importing)
|
|
175
216
|
this.showEmptyState();
|
|
176
217
|
this.updateCaptureActions();
|
|
177
218
|
this.maybeAutoCapture();
|
|
@@ -199,7 +240,8 @@ export class FrameGraphInspector {
|
|
|
199
240
|
this.workbench.showEmptyState('capturing', 'Capturing the next rendered frame…');
|
|
200
241
|
this.updateCaptureActions();
|
|
201
242
|
try {
|
|
202
|
-
const
|
|
243
|
+
const request = { timing: 'both' };
|
|
244
|
+
const snapshot = await this.captureSnapshotCallback(request);
|
|
203
245
|
if (this.destroyed || revision !== this.operationRevision)
|
|
204
246
|
return;
|
|
205
247
|
if (!snapshot) {
|
|
@@ -226,9 +268,9 @@ export class FrameGraphInspector {
|
|
|
226
268
|
}
|
|
227
269
|
}
|
|
228
270
|
/**
|
|
229
|
-
* Validates and synchronously displays a programmatic Snapshot 1.
|
|
271
|
+
* Validates and synchronously displays a programmatic Snapshot 1.2 value.
|
|
230
272
|
*
|
|
231
|
-
* @throws {@link FrameGraphSnapshotValidationError} if `snapshot` is invalid.
|
|
273
|
+
* @throws {@link @zenfg/snapshot!index.FrameGraphSnapshotValidationError | FrameGraphSnapshotValidationError} if `snapshot` is invalid.
|
|
232
274
|
*/
|
|
233
275
|
setSnapshot(snapshot) {
|
|
234
276
|
if (this.destroyed)
|
|
@@ -280,10 +322,17 @@ export class FrameGraphInspector {
|
|
|
280
322
|
});
|
|
281
323
|
const sourceFormat = decoded.snapshot.capture.migration?.sourceFormat;
|
|
282
324
|
if (sourceFormat) {
|
|
283
|
-
|
|
325
|
+
// The current import format can differ from retained historical provenance.
|
|
326
|
+
const sourceLabel = {
|
|
327
|
+
'legacy-v0': 'Legacy V0',
|
|
328
|
+
'legacy-candidate-v1': 'Legacy Candidate V1',
|
|
329
|
+
'snapshot-v1.1': 'Snapshot 1.1',
|
|
330
|
+
}[decoded.migrated && decoded.source !== 'v1' ? decoded.source : sourceFormat];
|
|
331
|
+
const version = decoded.snapshot.version;
|
|
332
|
+
const targetLabel = `Snapshot ${version.major}.${version.minor}`;
|
|
284
333
|
this.statusMessage = decoded.migrated
|
|
285
|
-
? `Imported ${sourceLabel} and migrated it to ZenFG
|
|
286
|
-
: `Imported
|
|
334
|
+
? `Imported ${sourceLabel} and migrated it to ZenFG ${targetLabel}.`
|
|
335
|
+
: `Imported ${targetLabel} with ${sourceLabel} migration provenance.`;
|
|
287
336
|
this.statusTone = 'neutral';
|
|
288
337
|
}
|
|
289
338
|
}
|
|
@@ -363,15 +412,17 @@ export class FrameGraphInspector {
|
|
|
363
412
|
this.protocolSnapshot = snapshot;
|
|
364
413
|
this.viewModel = viewModel;
|
|
365
414
|
this.graphView.fitOnNextRender = true;
|
|
415
|
+
this.graphView.captureRevision = (this.graphView.captureRevision ?? 0) + 1;
|
|
416
|
+
this.graphView.revealOnNextRender = undefined;
|
|
417
|
+
this.graphView.renderer?.cancelReveal?.();
|
|
366
418
|
this.hovered = undefined;
|
|
367
419
|
this.initialAutoCaptureAttempted = true;
|
|
368
420
|
this.statusMessage = undefined;
|
|
369
421
|
this.statusTone = 'neutral';
|
|
370
|
-
if (
|
|
371
|
-
this.selected = viewModel.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
422
|
+
if (this.selected?.kind === 'node' || this.selected?.kind === 'culled')
|
|
423
|
+
this.selected = resolveNodeSelection(viewModel, this.selected.id);
|
|
424
|
+
else if (this.selected && !selectionExists(viewModel, this.selected))
|
|
425
|
+
this.selected = undefined;
|
|
375
426
|
this.workbench.setSnapshot(viewModel, this.selected);
|
|
376
427
|
this.updateCaptureActions();
|
|
377
428
|
this.updateGraphControls();
|
|
@@ -393,7 +444,9 @@ export class FrameGraphInspector {
|
|
|
393
444
|
this.dom.removeEventListener('dragleave', this.handleDragLeave);
|
|
394
445
|
this.dom.removeEventListener('dragend', this.handleDragEnd);
|
|
395
446
|
this.dom.removeEventListener('drop', this.handleDrop);
|
|
447
|
+
this.themeController.destroy();
|
|
396
448
|
destroyGraph(this.graphView);
|
|
449
|
+
this.workbench.destroy();
|
|
397
450
|
this.dom.remove();
|
|
398
451
|
}
|
|
399
452
|
updateCaptureActions() {
|
|
@@ -420,9 +473,54 @@ export class FrameGraphInspector {
|
|
|
420
473
|
void this.captureSnapshot();
|
|
421
474
|
}
|
|
422
475
|
handleSelect(selection) {
|
|
476
|
+
if (!this.viewModel || !selectionExists(this.viewModel, selection))
|
|
477
|
+
return;
|
|
423
478
|
this.selected = selection;
|
|
424
479
|
this.workbench.setSelection(selection);
|
|
425
480
|
}
|
|
481
|
+
handleReveal(selection, tab) {
|
|
482
|
+
const snapshot = this.viewModel;
|
|
483
|
+
if (!snapshot || !selectionExists(snapshot, selection))
|
|
484
|
+
return;
|
|
485
|
+
if (tab === 'graph') {
|
|
486
|
+
const expanded = new Set(this.graphView.expandedGroupPaths);
|
|
487
|
+
const groupsEnabled = this.graphView.groupsEnabled;
|
|
488
|
+
const showResourceDeclarations = this.graphView.showResourceDeclarations;
|
|
489
|
+
if (selection.kind === 'resource')
|
|
490
|
+
this.graphView.showResourceDeclarations = true;
|
|
491
|
+
if (selection.kind === 'group')
|
|
492
|
+
this.graphView.groupsEnabled = true;
|
|
493
|
+
let groupId;
|
|
494
|
+
if (selection.kind === 'node')
|
|
495
|
+
groupId = snapshot.nodeById.get(selection.id)?.debugGroupId;
|
|
496
|
+
else if (selection.kind === 'resource')
|
|
497
|
+
groupId = snapshot.resourceById.get(selection.id)?.debugGroupId;
|
|
498
|
+
else if (selection.kind === 'group')
|
|
499
|
+
groupId = snapshot.groupByPathKey.get(selection.pathKey)?.parentId;
|
|
500
|
+
if (this.graphView.groupsEnabled && groupId) {
|
|
501
|
+
for (const id of snapshot.groupById.get(groupId)?.ancestorIds ?? []) {
|
|
502
|
+
const group = snapshot.groupById.get(id);
|
|
503
|
+
if (group)
|
|
504
|
+
this.graphView.expandedGroupPaths.add(group.pathKey);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const scene = resolveGraphScene(this.graphView, snapshot);
|
|
508
|
+
const availableIds = new Set([...scene.nodes, ...scene.edges].map((entry) => entry.id));
|
|
509
|
+
if (!(scene.interaction.primaryElementIdsBySelection.get(selectionKey(selection))?.some((id) => availableIds.has(id)))) {
|
|
510
|
+
this.graphView.groupsEnabled = groupsEnabled;
|
|
511
|
+
this.graphView.showResourceDeclarations = showResourceDeclarations;
|
|
512
|
+
this.graphView.expandedGroupPaths.clear();
|
|
513
|
+
for (const path of expanded)
|
|
514
|
+
this.graphView.expandedGroupPaths.add(path);
|
|
515
|
+
this.workbench.showNavigationIssue(selection.kind === 'culled' ? 'Culled passes are not part of Frame Flow.' : 'This object has no representation in Frame Flow.', selection);
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
this.graphView.revealOnNextRender = { selection, revision: ++this.revealRevision };
|
|
519
|
+
this.updateGraphControls();
|
|
520
|
+
}
|
|
521
|
+
this.handleSelect(selection);
|
|
522
|
+
this.workbench.reveal(selection, tab);
|
|
523
|
+
}
|
|
426
524
|
handleHover(selection) {
|
|
427
525
|
if (!this.viewModel || sameSelection(this.hovered, selection))
|
|
428
526
|
return;
|
|
@@ -430,13 +528,28 @@ export class FrameGraphInspector {
|
|
|
430
528
|
this.workbench.setHovered(selection);
|
|
431
529
|
}
|
|
432
530
|
updateGraphControls() {
|
|
531
|
+
const showDeclarations = this.graphView.showResourceDeclarations ?? true;
|
|
532
|
+
this.declarationsButton.classList.toggle('active', showDeclarations);
|
|
533
|
+
this.declarationsButton.setAttribute('aria-pressed', String(showDeclarations));
|
|
433
534
|
const hasGroups = (this.viewModel?.debugGroups.length ?? 0) > 0;
|
|
434
535
|
this.groupsButton.disabled = !hasGroups;
|
|
536
|
+
this.groupsButton.hidden = !hasGroups;
|
|
537
|
+
this.collapseGroupsButton.hidden = !hasGroups;
|
|
435
538
|
this.groupsButton.classList.toggle('active', hasGroups && this.graphView.groupsEnabled);
|
|
436
539
|
this.groupsButton.setAttribute('aria-pressed', hasGroups && this.graphView.groupsEnabled ? 'true' : 'false');
|
|
437
540
|
const hasExpanded = this.viewModel?.debugGroups.some((group) => this.graphView.expandedGroupPaths.has(group.pathKey)) ?? false;
|
|
438
541
|
this.collapseGroupsButton.disabled = !hasGroups || !this.graphView.groupsEnabled || !hasExpanded;
|
|
439
542
|
}
|
|
543
|
+
toggleDeclarations() {
|
|
544
|
+
this.handleHover(undefined);
|
|
545
|
+
this.graphView.showResourceDeclarations = !(this.graphView.showResourceDeclarations ?? true);
|
|
546
|
+
this.graphView.renderer?.cancelReveal?.();
|
|
547
|
+
this.graphView.revealOnNextRender = undefined;
|
|
548
|
+
this.graphView.anchorElementIdOnNextRender = undefined;
|
|
549
|
+
this.graphView.fitOnNextRender = true;
|
|
550
|
+
this.updateGraphControls();
|
|
551
|
+
this.workbench.refreshGraphStructure();
|
|
552
|
+
}
|
|
440
553
|
toggleGroups() {
|
|
441
554
|
if (!this.viewModel?.debugGroups.length)
|
|
442
555
|
return;
|
|
@@ -499,14 +612,9 @@ export class FrameGraphInspector {
|
|
|
499
612
|
export function mountFrameGraphInspector(host, options) {
|
|
500
613
|
const inspector = new FrameGraphInspector(options);
|
|
501
614
|
host.appendChild(inspector.dom);
|
|
615
|
+
inspector.refreshTheme();
|
|
502
616
|
return inspector;
|
|
503
617
|
}
|
|
504
|
-
function createGraphIconButton(icon, title, onClick) {
|
|
505
|
-
const button = createToolbarButton('', title, onClick);
|
|
506
|
-
button.classList.add('zenfg-inspector-icon-button');
|
|
507
|
-
button.appendChild(createPanelIcon(icon));
|
|
508
|
-
return button;
|
|
509
|
-
}
|
|
510
618
|
async function writeTextToClipboard(text) {
|
|
511
619
|
if (navigator.clipboard?.writeText) {
|
|
512
620
|
await navigator.clipboard.writeText(text);
|
|
@@ -545,7 +653,7 @@ function formatImportLimit(bytes) {
|
|
|
545
653
|
: `${bytes} bytes`;
|
|
546
654
|
}
|
|
547
655
|
function formatIssues(issues) {
|
|
548
|
-
return issues.
|
|
656
|
+
return issues.map((issue) => `${issue.path || '/'}: ${issue.message}`).join('\n');
|
|
549
657
|
}
|
|
550
658
|
function isFileDrag(event) {
|
|
551
659
|
return Array.from(event.dataTransfer?.types ?? []).includes('Files');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FrameGraphInspector.js","sourceRoot":"","sources":["../src/FrameGraphInspector.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tFrameGraphSnapshotValidationError,\n\tdecodeFrameGraphSnapshot,\n\tparseFrameGraphSnapshot,\n\tstringifyFrameGraphSnapshot,\n\ttype FrameGraphSnapshot,\n} from '@zenfg/snapshot';\nimport {\n\tcreateDebugViewModel,\n\ttype FrameGraphDebugSnapshotSource,\n\ttype FrameGraphDebugViewModel,\n} from './debugCaptureModel.ts';\nimport { createToolbarButton } from './panelDomHelpers.ts';\nimport { createPanelIcon } from './panelIcons.ts';\nimport {\n\tdestroyGraph,\n\tfitGraph,\n} from './panelGraphView.ts';\nimport { graphGroupElementId } from './panelGraphScene.ts';\nimport { selectionExists } from './panelSelection.ts';\nimport type { GraphViewState, Selection } from './panelTypes.ts';\nimport { ensureFrameGraphInspectorStyles } from './styles.ts';\nimport { sameSelection, type WorkbenchCallbacks } from './panelWorkbenchHelpers.ts';\nimport { FrameGraphDebugWorkbench } from './panelWorkbenchView.ts';\n\n/** Construction and safety limits for an embedded {@link FrameGraphInspector}. */\nexport type FrameGraphInspectorOptions = {\n\t/**\n\t * Product label shown in the workbench command bar. Pass `false` to hide\n\t * visible branding while retaining the inspector's accessible name.\n\t *\n\t * @defaultValue `\"ZenFG Inspector\"`\n\t */\n\tbranding?: string | false;\n\t/**\n\t * Produces a live snapshot when capture is requested. The inspector awaits\n\t * promises and displays thrown or rejected errors in its status area.\n\t */\n\tcaptureSnapshot?: () => FrameGraphSnapshot | undefined | Promise<FrameGraphSnapshot | undefined>;\n\t/**\n\t * Maximum accepted import size in bytes.\n\t *\n\t * @defaultValue `67108864` (64 MiB)\n\t */\n\tmaxImportBytes?: number;\n\t/**\n\t * Maximum graph nodes plus edges accepted by automatic layout.\n\t *\n\t * @defaultValue `5000`\n\t */\n\tmaxGraphElements?: number;\n};\n\nconst DEFAULT_MAX_IMPORT_BYTES = 64 * 1024 * 1024;\nconst DEFAULT_MAX_GRAPH_ELEMENTS = 5_000;\nconst DEFAULT_BRANDING = 'ZenFG Inspector';\n\n/**\n * Browser lifecycle controller for one embeddable FrameGraph inspector.\n *\n * @remarks The constructor creates, but does not append, {@link dom}. Use\n * {@link mountFrameGraphInspector} for the common append-and-return workflow.\n * Async capture, import, and clipboard failures are reported in the UI. Call\n * {@link destroy} when the controller is no longer needed.\n *\n * @example\n * ```ts\n * const inspector = new FrameGraphInspector({ captureSnapshot: capture });\n * document.body.append(inspector.dom);\n * // Later:\n * inspector.destroy();\n * ```\n */\nexport class FrameGraphInspector {\n\t/** Root element owned by this inspector instance. */\n\treadonly dom = document.createElement('section');\n\n\tprivate readonly body = document.createElement('div');\n\tprivate readonly content = document.createElement('div');\n\tprivate readonly dropOverlay = document.createElement('div');\n\tprivate readonly groupsButton: HTMLButtonElement;\n\tprivate readonly collapseGroupsButton: HTMLButtonElement;\n\tprivate readonly graphView: GraphViewState;\n\tprivate readonly workbench: FrameGraphDebugWorkbench;\n\tprivate captureSnapshotCallback: FrameGraphInspectorOptions['captureSnapshot'];\n\tprivate protocolSnapshot: FrameGraphSnapshot | undefined;\n\tprivate operationRevision = 0;\n\tprivate viewModel: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\tprivate hovered: Selection | undefined;\n\tprivate capturing = false;\n\tprivate importing = false;\n\tprivate copying = false;\n\tprivate copied = false;\n\tprivate initialAutoCaptureAttempted = false;\n\tprivate statusMessage: string | undefined;\n\tprivate statusTone: 'neutral' | 'error' = 'neutral';\n\tprivate destroyed = false;\n\tprivate copyFeedbackTimeout: number | undefined;\n\tprivate readonly maxImportBytes: number;\n\tprivate dragDepth = 0;\n\tprivate readonly handleDragEnter = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event)) return;\n\t\tevent.preventDefault();\n\t\tthis.dragDepth += 1;\n\t\tthis.setDropActive(true);\n\t};\n\tprivate readonly handleDragOver = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event)) return;\n\t\tevent.preventDefault();\n\t\tif (event.dataTransfer) event.dataTransfer.dropEffect = 'copy';\n\t\tthis.setDropActive(true);\n\t};\n\tprivate readonly handleDragLeave = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event) && this.dragDepth === 0) return;\n\t\tthis.dragDepth = Math.max(0, this.dragDepth - 1);\n\t\tif (this.dragDepth === 0) this.setDropActive(false);\n\t};\n\tprivate readonly handleDragEnd = (): void => this.clearDropState();\n\tprivate readonly handleDrop = (event: DragEvent): void => {\n\t\tconst file = event.dataTransfer?.files?.[0];\n\t\tif (!file) return;\n\t\tevent.preventDefault();\n\t\tthis.clearDropState();\n\t\tvoid this.importSnapshot(file);\n\t};\n\n\t/**\n\t * Creates a detached inspector UI.\n\t *\n\t * @throws If a configured numeric limit is not a non-negative safe integer,\n\t * or if browser DOM globals are unavailable.\n\t */\n\tconstructor(options: FrameGraphInspectorOptions = {}) {\n\t\tensureFrameGraphInspectorStyles();\n\t\tthis.captureSnapshotCallback = options.captureSnapshot;\n\t\tthis.maxImportBytes = normalizeMaxImportBytes(options.maxImportBytes);\n\t\tconst branding = options.branding ?? DEFAULT_BRANDING;\n\t\tthis.dom.className = 'zenfg-inspector';\n\t\tthis.dom.id = createInspectorId();\n\t\tthis.dom.setAttribute('role', 'region');\n\t\tthis.dom.setAttribute('aria-label', branding === false ? DEFAULT_BRANDING : branding);\n\t\tthis.body.className = 'zenfg-inspector-body';\n\t\tthis.content.className = 'zenfg-inspector-content';\n\t\tthis.dropOverlay.className = 'zenfg-inspector-drop-overlay';\n\t\tthis.dropOverlay.hidden = true;\n\t\tthis.dropOverlay.setAttribute('aria-hidden', 'true');\n\t\tconst dropTitle = document.createElement('strong');\n\t\tdropTitle.textContent = 'Drop snapshot to open';\n\t\tconst dropDetail = document.createElement('span');\n\t\tdropDetail.textContent = 'The first file will be imported locally.';\n\t\tthis.dropOverlay.append(dropTitle, dropDetail);\n\n\t\tconst graphLegend = document.createElement('div');\n\t\tgraphLegend.className = 'zenfg-inspector-graph-legend';\n\t\tgraphLegend.setAttribute('aria-label', 'Graph legend');\n\t\tthis.graphView = {\n\t\t\thost: document.createElement('div'),\n\t\t\ttoolbar: document.createElement('div'),\n\t\t\tlegend: graphLegend,\n\t\t\tlayoutElementBudget: normalizeLimit(options.maxGraphElements, DEFAULT_MAX_GRAPH_ELEMENTS, 'maxGraphElements'),\n\t\t\tgroupsEnabled: true,\n\t\t\texpandedGroupPaths: new Set(),\n\t\t\tfitOnNextRender: true,\n\t\t};\n\t\tthis.graphView.host.className = 'zenfg-inspector-graph';\n\t\tthis.graphView.toolbar.className = 'zenfg-inspector-graph-toolbar';\n\t\tthis.graphView.toolbar.setAttribute('role', 'toolbar');\n\t\tthis.graphView.toolbar.setAttribute('aria-label', 'Frame graph view controls');\n\n\t\tthis.groupsButton = createToolbarButton('Groups', 'Toggle diagnostic group projection', () => this.toggleGroups());\n\t\tthis.collapseGroupsButton = createToolbarButton('Collapse All', 'Collapse every diagnostic group', () => this.collapseAllGroups());\n\n\t\tconst actionControls = document.createElement('div');\n\t\tactionControls.className = 'zenfg-inspector-graph-action-controls';\n\t\tactionControls.append(\n\t\t\tthis.groupsButton,\n\t\t\tthis.collapseGroupsButton,\n\t\t\tcreateGraphIconButton('fit', 'Fit graph to view', () => fitGraph(this.graphView)),\n\t\t);\n\t\tthis.graphView.toolbar.append(graphLegend, actionControls);\n\n\t\tconst callbacks: WorkbenchCallbacks = {\n\t\t\tonSelect: (selection) => this.handleSelect(selection),\n\t\t\tonHover: (selection) => this.handleHover(selection),\n\t\t\tonGroupToggle: (pathKey) => this.toggleGroup(pathKey),\n\t\t\tisGroupExpanded: (pathKey) => this.graphView.expandedGroupPaths.has(pathKey),\n\t\t};\n\t\tthis.workbench = new FrameGraphDebugWorkbench(this.graphView, callbacks, {\n\t\t\tonCapture: () => { void this.captureSnapshot(); },\n\t\t\tonImport: (file) => { void this.importSnapshot(file); },\n\t\t\tonDownload: () => this.downloadSnapshot(),\n\t\t\tonCopyJson: () => { void this.copySnapshotJson(); },\n\t\t}, {\n\t\t\tbranding,\n\t\t\tidPrefix: this.dom.id,\n\t\t});\n\t\tthis.content.append(this.workbench.root);\n\t\tthis.body.appendChild(this.content);\n\t\tthis.dom.append(this.body, this.dropOverlay);\n\t\tthis.dom.addEventListener('dragenter', this.handleDragEnter);\n\t\tthis.dom.addEventListener('dragover', this.handleDragOver);\n\t\tthis.dom.addEventListener('dragleave', this.handleDragLeave);\n\t\tthis.dom.addEventListener('dragend', this.handleDragEnd);\n\t\tthis.dom.addEventListener('drop', this.handleDrop);\n\t\tthis.updateCaptureActions();\n\t\tthis.updateGraphControls();\n\t\tthis.showEmptyState();\n\t\tqueueMicrotask(() => this.maybeAutoCapture());\n\t}\n\n\t/**\n\t * Replaces or removes the live-capture provider.\n\t *\n\t * @remarks Installing a provider may immediately begin an asynchronous\n\t * capture when no snapshot is displayed.\n\t */\n\tsetCaptureSnapshotProvider(provider: FrameGraphInspectorOptions['captureSnapshot']): void {\n\t\tconst changed = this.captureSnapshotCallback !== provider;\n\t\tthis.captureSnapshotCallback = provider;\n\t\tif (changed && !this.viewModel) this.initialAutoCaptureAttempted = false;\n\t\tif (!provider && !this.viewModel) this.showEmptyState();\n\t\tthis.updateCaptureActions();\n\t\tthis.maybeAutoCapture();\n\t}\n\n\t/**\n\t * Requests and displays a live snapshot from the configured provider.\n\t *\n\t * @remarks Concurrent requests are coalesced. Provider errors, invalid\n\t * snapshots, and an unavailable provider are displayed in the inspector and\n\t * do not reject the returned promise.\n\t */\n\tasync captureSnapshot(): Promise<void> {\n\t\tif (this.destroyed || this.capturing) return;\n\t\tif (!this.captureSnapshotCallback) {\n\t\t\tthis.reportCaptureIssue('Waiting for a FrameGraph capture source.');\n\t\t\treturn;\n\t\t}\n\t\tconst revision = ++this.operationRevision;\n\t\tthis.importing = false;\n\t\tthis.capturing = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tif (!this.viewModel) this.workbench.showEmptyState('capturing', 'Capturing the next rendered frame…');\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tconst snapshot = await this.captureSnapshotCallback();\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tif (!snapshot) {\n\t\t\t\tthis.reportCaptureIssue('No snapshot was produced. Capture again when rendering is active.');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst decoded = decodeFrameGraphSnapshot(snapshot);\n\t\t\tif (!decoded.ok) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to capture FrameGraph: ${formatIssues(decoded.issues)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.applySnapshot(decoded.snapshot, { kind: 'live', label: 'Live Capture' });\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to capture FrameGraph: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\tif (revision === this.operationRevision) this.capturing = false;\n\t\t\tif (!this.destroyed && revision === this.operationRevision) this.updateCaptureActions();\n\t\t}\n\t}\n\n\t/**\n\t * Validates and synchronously displays a programmatic Snapshot 1.1 value.\n\t *\n\t * @throws {@link FrameGraphSnapshotValidationError} if `snapshot` is invalid.\n\t */\n\tsetSnapshot(snapshot: FrameGraphSnapshot): void {\n\t\tif (this.destroyed) return;\n\t\tthis.operationRevision += 1;\n\t\tthis.capturing = false;\n\t\tthis.importing = false;\n\t\tconst decoded = decodeFrameGraphSnapshot(snapshot);\n\t\tif (!decoded.ok) throw new FrameGraphSnapshotValidationError(decoded.issues);\n\t\tthis.applySnapshot(decoded.snapshot, { kind: 'programmatic', label: 'Programmatic' });\n\t}\n\n\t/** Returns the currently displayed canonical snapshot, if any. */\n\tgetSnapshot(): FrameGraphSnapshot | undefined {\n\t\treturn this.protocolSnapshot;\n\t}\n\n\t/**\n\t * Reads, migrates, validates, and displays a snapshot JSON file.\n\t *\n\t * @remarks Files above `maxImportBytes`, read failures, invalid JSON, and\n\t * validation failures are displayed in the UI and do not reject the promise.\n\t */\n\tasync importSnapshot(file: File): Promise<void> {\n\t\tif (this.destroyed) return;\n\t\tconst revision = ++this.operationRevision;\n\t\tthis.capturing = false;\n\t\tthis.importing = false;\n\t\tif (file.size > this.maxImportBytes) {\n\t\t\tthis.reportCaptureIssue(`Import exceeds the ${formatImportLimit(this.maxImportBytes)} limit.`);\n\t\t\treturn;\n\t\t}\n\t\tthis.importing = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tconst text = await file.text();\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tconst decoded = parseFrameGraphSnapshot(text);\n\t\t\tif (!decoded.ok) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to import snapshot: ${formatIssues(decoded.issues)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.applySnapshot(decoded.snapshot, {\n\t\t\t\tkind: 'file',\n\t\t\t\tlabel: file.name || 'Imported JSON',\n\t\t\t});\n\t\t\tconst sourceFormat = decoded.snapshot.capture.migration?.sourceFormat;\n\t\t\tif (sourceFormat) {\n\t\t\t\tconst sourceLabel = sourceFormat === 'legacy-v0' ? 'Legacy V0' : 'Legacy Candidate V1';\n\t\t\t\tthis.statusMessage = decoded.migrated\n\t\t\t\t\t? `Imported ${sourceLabel} and migrated it to ZenFG Snapshot V1.`\n\t\t\t\t\t: `Imported Snapshot V1 with ${sourceLabel} migration provenance.`;\n\t\t\t\tthis.statusTone = 'neutral';\n\t\t\t}\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to import snapshot: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\tif (revision === this.operationRevision) this.importing = false;\n\t\t\tif (!this.destroyed && revision === this.operationRevision) this.updateCaptureActions();\n\t\t}\n\t}\n\n\t/** Downloads the displayed snapshot as pretty-printed canonical JSON. */\n\tdownloadSnapshot(): void {\n\t\tif (this.destroyed || !this.protocolSnapshot) return;\n\t\tconst json = stringifyFrameGraphSnapshot(this.protocolSnapshot, { pretty: true });\n\t\tconst url = URL.createObjectURL(new Blob([json], { type: 'application/json;charset=utf-8' }));\n\t\tconst anchor = document.createElement('a');\n\t\tanchor.href = url;\n\t\tanchor.download = `frame-graph-${this.protocolSnapshot.capture.frameIndex}.fgsnapshot.json`;\n\t\tanchor.click();\n\t\tURL.revokeObjectURL(url);\n\t}\n\n\t/**\n\t * Copies the displayed snapshot as pretty-printed canonical JSON.\n\t *\n\t * @remarks Clipboard failures are shown in the UI and do not reject the\n\t * returned promise. A legacy `document.execCommand` fallback is used when the\n\t * async Clipboard API is unavailable.\n\t */\n\tasync copySnapshotJson(): Promise<void> {\n\t\tif (this.destroyed || this.copying || !this.protocolSnapshot) return;\n\t\tconst snapshot = this.protocolSnapshot;\n\t\tconst revision = this.operationRevision;\n\t\tthis.copying = true;\n\t\tthis.copied = false;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tawait writeTextToClipboard(stringifyFrameGraphSnapshot(snapshot, { pretty: true }));\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tthis.copied = true;\n\t\t\tif (this.copyFeedbackTimeout !== undefined) window.clearTimeout(this.copyFeedbackTimeout);\n\t\t\tthis.copyFeedbackTimeout = window.setTimeout(() => {\n\t\t\t\tthis.copied = false;\n\t\t\t\tthis.copyFeedbackTimeout = undefined;\n\t\t\t\tthis.updateCaptureActions();\n\t\t\t}, 1200);\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.statusMessage = `Failed to copy snapshot: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\t}\n\t\t\tconsole.warn('Failed to copy FrameGraph Snapshot.', error);\n\t\t}\n\t\tfinally {\n\t\t\tthis.copying = false;\n\t\t\tif (!this.destroyed) this.updateCaptureActions();\n\t\t}\n\t}\n\n\tprivate applySnapshot(snapshot: FrameGraphSnapshot, source: FrameGraphDebugSnapshotSource): void {\n\t\tconst viewModel = createDebugViewModel(snapshot, source);\n\t\tthis.copied = false;\n\t\tif (this.copyFeedbackTimeout !== undefined) {\n\t\t\twindow.clearTimeout(this.copyFeedbackTimeout);\n\t\t\tthis.copyFeedbackTimeout = undefined;\n\t\t}\n\t\tthis.protocolSnapshot = snapshot;\n\t\tthis.viewModel = viewModel;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.hovered = undefined;\n\t\tthis.initialAutoCaptureAttempted = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tif (!this.selected || !selectionExists(viewModel, this.selected)) {\n\t\t\tthis.selected = viewModel.nodes[0]\n\t\t\t\t? { kind: 'node', id: viewModel.nodes[0].id }\n\t\t\t\t: undefined;\n\t\t}\n\t\tthis.workbench.setSnapshot(viewModel, this.selected);\n\t\tthis.updateCaptureActions();\n\t\tthis.updateGraphControls();\n\t}\n\n\t/**\n\t * Idempotently cancels pending UI results, releases graph resources, and\n\t * removes the inspector workbench. Do not reuse the controller afterward.\n\t */\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\t\tthis.operationRevision += 1;\n\t\tif (this.copyFeedbackTimeout !== undefined) window.clearTimeout(this.copyFeedbackTimeout);\n\t\tthis.clearDropState();\n\t\tthis.dom.removeEventListener('dragenter', this.handleDragEnter);\n\t\tthis.dom.removeEventListener('dragover', this.handleDragOver);\n\t\tthis.dom.removeEventListener('dragleave', this.handleDragLeave);\n\t\tthis.dom.removeEventListener('dragend', this.handleDragEnd);\n\t\tthis.dom.removeEventListener('drop', this.handleDrop);\n\t\tdestroyGraph(this.graphView);\n\t\tthis.dom.remove();\n\t}\n\n\tprivate updateCaptureActions(): void {\n\t\tthis.workbench.setSnapshotActionState({\n\t\t\tproviderAvailable: Boolean(this.captureSnapshotCallback),\n\t\t\thasCapture: Boolean(this.viewModel),\n\t\t\tcapturing: this.capturing,\n\t\t\timporting: this.importing,\n\t\t\tcopying: this.copying,\n\t\t\tcopied: this.copied,\n\t\t\tmessage: this.viewModel ? this.statusMessage : undefined,\n\t\t\tmessageTone: this.statusTone,\n\t\t});\n\t}\n\n\tprivate maybeAutoCapture(): void {\n\t\tif (\n\t\t\tthis.destroyed\n\t\t\t|| this.viewModel\n\t\t\t|| this.initialAutoCaptureAttempted\n\t\t\t|| this.capturing\n\t\t\t|| this.importing\n\t\t\t|| !this.captureSnapshotCallback\n\t\t) return;\n\t\tthis.initialAutoCaptureAttempted = true;\n\t\tvoid this.captureSnapshot();\n\t}\n\tprivate handleSelect(selection: Selection): void {\n\t\tthis.selected = selection;\n\t\tthis.workbench.setSelection(selection);\n\t}\n\n\tprivate handleHover(selection: Selection | undefined): void {\n\t\tif (!this.viewModel || sameSelection(this.hovered, selection)) return;\n\t\tthis.hovered = selection;\n\t\tthis.workbench.setHovered(selection);\n\t}\n\n\tprivate updateGraphControls(): void {\n\t\tconst hasGroups = (this.viewModel?.debugGroups.length ?? 0) > 0;\n\t\tthis.groupsButton.disabled = !hasGroups;\n\t\tthis.groupsButton.classList.toggle('active', hasGroups && this.graphView.groupsEnabled);\n\t\tthis.groupsButton.setAttribute('aria-pressed', hasGroups && this.graphView.groupsEnabled ? 'true' : 'false');\n\t\tconst hasExpanded = this.viewModel?.debugGroups.some((group) => this.graphView.expandedGroupPaths.has(group.pathKey)) ?? false;\n\t\tthis.collapseGroupsButton.disabled = !hasGroups || !this.graphView.groupsEnabled || !hasExpanded;\n\t}\n\n\tprivate toggleGroups(): void {\n\t\tif (!this.viewModel?.debugGroups.length) return;\n\t\tthis.handleHover(undefined);\n\t\tthis.graphView.groupsEnabled = !this.graphView.groupsEnabled;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate toggleGroup(pathKey: string): void {\n\t\tthis.handleHover(undefined);\n\t\tif (this.graphView.expandedGroupPaths.has(pathKey)) this.graphView.expandedGroupPaths.delete(pathKey);\n\t\telse this.graphView.expandedGroupPaths.add(pathKey);\n\t\tthis.graphView.anchorElementIdOnNextRender = graphGroupElementId(pathKey);\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate collapseAllGroups(): void {\n\t\tif (this.graphView.expandedGroupPaths.size === 0) return;\n\t\tthis.handleHover(undefined);\n\t\tthis.graphView.expandedGroupPaths.clear();\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate showEmptyState(): void {\n\t\tconst providerAvailable = Boolean(this.captureSnapshotCallback);\n\t\tthis.workbench.showEmptyState(\n\t\t\t'empty',\n\t\t\tproviderAvailable\n\t\t\t\t? 'No capture yet. Use Capture to request the next rendered frame.'\n\t\t\t\t: 'Drop a ZenFG Snapshot here or choose Import.',\n\t\t\tproviderAvailable ? undefined : 'Files are processed locally in your browser.',\n\t\t);\n\t}\n\n\tprivate setDropActive(active: boolean): void {\n\t\tif (this.destroyed) return;\n\t\tthis.dropOverlay.hidden = !active;\n\t\tthis.dom.classList.toggle('drop-active', active);\n\t}\n\n\tprivate clearDropState(): void {\n\t\tthis.dragDepth = 0;\n\t\tthis.dropOverlay.hidden = true;\n\t\tthis.dom.classList.remove('drop-active');\n\t}\n\n\tprivate reportCaptureIssue(message: string): void {\n\t\tthis.statusMessage = message;\n\t\tthis.statusTone = 'error';\n\t\tif (!this.viewModel) this.workbench.showEmptyState('error', message);\n\t\tthis.updateCaptureActions();\n\t}\n}\n\n/**\n * Creates an inspector, appends its root element to `host`, and returns its\n * lifecycle controller.\n *\n * @throws If inspector construction fails; see {@link FrameGraphInspector}.\n */\nexport function mountFrameGraphInspector(host: HTMLElement, options?: FrameGraphInspectorOptions): FrameGraphInspector {\n\tconst inspector = new FrameGraphInspector(options);\n\thost.appendChild(inspector.dom);\n\treturn inspector;\n}\n\nfunction createGraphIconButton(icon: 'fit', title: string, onClick: () => void): HTMLButtonElement {\n\tconst button = createToolbarButton('', title, onClick);\n\tbutton.classList.add('zenfg-inspector-icon-button');\n\tbutton.appendChild(createPanelIcon(icon));\n\treturn button;\n}\n\nasync function writeTextToClipboard(text: string): Promise<void> {\n\tif (navigator.clipboard?.writeText) {\n\t\tawait navigator.clipboard.writeText(text);\n\t\treturn;\n\t}\n\tconst textArea = document.createElement('textarea');\n\ttextArea.value = text;\n\ttextArea.setAttribute('readonly', 'true');\n\ttextArea.style.position = 'fixed';\n\ttextArea.style.left = '-9999px';\n\ttextArea.style.top = '0';\n\tdocument.body.appendChild(textArea);\n\ttextArea.select();\n\ttry {\n\t\tif (!document.execCommand('copy')) throw new Error('document.execCommand(\"copy\") returned false.');\n\t}\n\tfinally {\n\t\ttextArea.remove();\n\t}\n}\n\nfunction normalizeMaxImportBytes(value: number | undefined): number {\n\treturn normalizeLimit(value, DEFAULT_MAX_IMPORT_BYTES, 'maxImportBytes');\n}\n\nfunction normalizeLimit(value: number | undefined, fallback: number, name: string): number {\n\tif (value === undefined) return fallback;\n\tif (!Number.isSafeInteger(value) || value < 0) {\n\t\tthrow new Error(`${name} must be a non-negative safe integer.`);\n\t}\n\treturn value;\n}\n\nfunction formatImportLimit(bytes: number): string {\n\treturn bytes >= 1024 * 1024 && bytes % (1024 * 1024) === 0\n\t\t? `${bytes / (1024 * 1024)} MiB`\n\t\t: `${bytes} bytes`;\n}\n\nfunction formatIssues(issues: readonly { readonly path: string; readonly message: string }[]): string {\n\treturn issues.slice(0, 3).map((issue) => `${issue.path || '/'}: ${issue.message}`).join('; ');\n}\n\nfunction isFileDrag(event: DragEvent): boolean {\n\treturn Array.from(event.dataTransfer?.types ?? []).includes('Files');\n}\n\nlet nextInspectorId = 0;\nfunction createInspectorId(): string {\n\tnextInspectorId += 1;\n\treturn `zenfg-inspector-${nextInspectorId}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FrameGraphInspector.js","sourceRoot":"","sources":["../src/FrameGraphInspector.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FrameGraphCaptureRequest } from './capture.ts';\nimport type { InspectorTheme } from './theme.ts';\nimport { InspectorThemeController, resolveGraphTheme } from './panelTheme.ts';\nimport {\n\tFrameGraphSnapshotValidationError,\n\tdecodeFrameGraphSnapshot,\n\tparseFrameGraphSnapshot,\n\tstringifyFrameGraphSnapshot,\n\ttype FrameGraphSnapshot,\n} from '@zenfg/snapshot';\nimport {\n\tcreateDebugViewModel,\n\ttype FrameGraphDebugSnapshotSource,\n\ttype FrameGraphDebugViewModel,\n} from './debugCaptureModel.ts';\nimport { createToolbarButton } from './panelDomHelpers.ts';\nimport {\n\tdestroyGraph,\n\tfitGraph,\n\tresolveGraphScene,\n\trenderGraphLegend,\n} from './panelGraphView.ts';\nimport { graphGroupElementId, selectionKey } from './panelGraphScene.ts';\nimport { resolveNodeSelection, selectionExists } from './panelSelection.ts';\nimport type { GraphViewState, Selection, WorkbenchTab } from './panelTypes.ts';\nimport { ensureFrameGraphInspectorStyles } from './styles.ts';\nimport { sameSelection, type WorkbenchCallbacks } from './panelWorkbenchHelpers.ts';\nimport { FrameGraphDebugWorkbench } from './panelWorkbenchView.ts';\n\n/** Construction and safety limits for an embedded {@link FrameGraphInspector}. */\nexport type FrameGraphInspectorOptions = {\n\t/** Optional CSS theme. Without one, host variables inherit over the Storm defaults. */\n\ttheme?: InspectorTheme;\n\t/**\n\t * Product label shown in the workbench command bar. Pass `false` to hide\n\t * visible branding while retaining the inspector's accessible name.\n\t *\n\t * @defaultValue `\"ZenFG Inspector\"`\n\t */\n\tbranding?: string | false;\n\t/**\n\t * Produces a live snapshot when capture is requested. The inspector awaits\n\t * promises and displays thrown or rejected errors in its status area.\n\t */\n\tcaptureSnapshot?: (request: FrameGraphCaptureRequest) => FrameGraphSnapshot | undefined | Promise<FrameGraphSnapshot | undefined>;\n\t/**\n\t * Maximum accepted import size in bytes.\n\t *\n\t * @defaultValue `67108864` (64 MiB)\n\t */\n\tmaxImportBytes?: number;\n\t/**\n\t * Maximum graph nodes plus edges accepted by automatic layout.\n\t *\n\t * @defaultValue `5000`\n\t */\n\tmaxGraphElements?: number;\n};\n\nconst DEFAULT_MAX_IMPORT_BYTES = 64 * 1024 * 1024;\nconst DEFAULT_MAX_GRAPH_ELEMENTS = 5_000;\nconst DEFAULT_BRANDING = 'ZenFG Inspector';\n\n/**\n * Browser lifecycle controller for one embeddable FrameGraph inspector.\n *\n * @remarks The constructor creates, but does not append, {@link dom}. Use\n * {@link mountFrameGraphInspector} for the common append-and-return workflow.\n * Async capture, import, and clipboard failures are reported in the UI. Call\n * {@link destroy} when the controller is no longer needed.\n *\n * @example\n * ```ts\n * const inspector = new FrameGraphInspector({ captureSnapshot: capture });\n * document.body.append(inspector.dom);\n * // Later:\n * inspector.destroy();\n * ```\n */\nexport class FrameGraphInspector {\n\t/** Root element owned by this inspector instance. */\n\treadonly dom = document.createElement('section');\n\tprivate readonly themeController = new InspectorThemeController(this.dom);\n\n\tprivate readonly body = document.createElement('div');\n\tprivate readonly content = document.createElement('div');\n\tprivate readonly dropOverlay = document.createElement('div');\n\tprivate readonly groupsButton: HTMLButtonElement;\n\tprivate readonly declarationsButton: HTMLButtonElement;\n\tprivate readonly collapseGroupsButton: HTMLButtonElement;\n\tprivate readonly graphView: GraphViewState;\n\tprivate readonly workbench: FrameGraphDebugWorkbench;\n\tprivate captureSnapshotCallback: FrameGraphInspectorOptions['captureSnapshot'];\n\tprivate protocolSnapshot: FrameGraphSnapshot | undefined;\n\tprivate operationRevision = 0;\n\tprivate viewModel: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\tprivate hovered: Selection | undefined;\n\tprivate capturing = false;\n\tprivate importing = false;\n\tprivate copying = false;\n\tprivate copied = false;\n\tprivate initialAutoCaptureAttempted = false;\n\tprivate statusMessage: string | undefined;\n\tprivate statusTone: 'neutral' | 'error' = 'neutral';\n\tprivate destroyed = false;\n\tprivate copyFeedbackTimeout: number | undefined;\n\tprivate readonly maxImportBytes: number;\n\tprivate dragDepth = 0;\n\tprivate revealRevision = 0;\n\tprivate readonly handleDragEnter = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event)) return;\n\t\tevent.preventDefault();\n\t\tthis.dragDepth += 1;\n\t\tthis.setDropActive(true);\n\t};\n\tprivate readonly handleDragOver = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event)) return;\n\t\tevent.preventDefault();\n\t\tif (event.dataTransfer) event.dataTransfer.dropEffect = 'copy';\n\t\tthis.setDropActive(true);\n\t};\n\tprivate readonly handleDragLeave = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event) && this.dragDepth === 0) return;\n\t\tthis.dragDepth = Math.max(0, this.dragDepth - 1);\n\t\tif (this.dragDepth === 0) this.setDropActive(false);\n\t};\n\tprivate readonly handleDragEnd = (): void => this.clearDropState();\n\tprivate readonly handleDrop = (event: DragEvent): void => {\n\t\tconst file = event.dataTransfer?.files?.[0];\n\t\tif (!file) return;\n\t\tevent.preventDefault();\n\t\tthis.clearDropState();\n\t\tvoid this.importSnapshot(file);\n\t};\n\n\t/**\n\t * Creates a detached inspector UI.\n\t *\n\t * @throws If a configured numeric limit is not a non-negative safe integer,\n\t * or if browser DOM globals are unavailable.\n\t */\n\tconstructor(options: FrameGraphInspectorOptions = {}) {\n\t\tensureFrameGraphInspectorStyles();\n\t\tthis.captureSnapshotCallback = options.captureSnapshot;\n\t\tthis.maxImportBytes = normalizeMaxImportBytes(options.maxImportBytes);\n\t\tconst branding = options.branding ?? DEFAULT_BRANDING;\n\t\tthis.dom.className = 'zenfg-inspector';\n\t\tthis.dom.id = createInspectorId();\n\t\tthis.dom.setAttribute('role', 'region');\n\t\tthis.dom.setAttribute('aria-label', branding === false ? DEFAULT_BRANDING : branding);\n\t\tthis.body.className = 'zenfg-inspector-body';\n\t\tthis.content.className = 'zenfg-inspector-content';\n\t\tthis.dropOverlay.className = 'zenfg-inspector-drop-overlay';\n\t\tthis.dropOverlay.hidden = true;\n\t\tthis.dropOverlay.setAttribute('aria-hidden', 'true');\n\t\tconst dropTitle = document.createElement('strong');\n\t\tdropTitle.textContent = 'Drop snapshot to open';\n\t\tconst dropDetail = document.createElement('span');\n\t\tdropDetail.textContent = 'The first file will be imported locally.';\n\t\tthis.dropOverlay.append(dropTitle, dropDetail);\n\n\t\tconst graphLegend = document.createElement('div');\n\t\tgraphLegend.className = 'zenfg-inspector-graph-legend';\n\t\tgraphLegend.setAttribute('aria-label', 'Graph legend');\n\t\tthis.graphView = {\n\t\t\thost: document.createElement('div'),\n\t\t\ttoolbar: document.createElement('div'),\n\t\t\tlegend: graphLegend,\n\t\t\trefreshTheme: () => this.refreshTheme(),\n\t\t\tlayoutElementBudget: normalizeLimit(options.maxGraphElements, DEFAULT_MAX_GRAPH_ELEMENTS, 'maxGraphElements'),\n\t\t\tgroupsEnabled: true,\n\t\t\tshowResourceDeclarations: true,\n\t\t\texpandedGroupPaths: new Set(),\n\t\t\tfitOnNextRender: true,\n\t\t};\n\t\tthis.graphView.host.className = 'zenfg-inspector-graph';\n\t\tthis.graphView.toolbar.className = 'zenfg-inspector-graph-toolbar';\n\t\tthis.graphView.toolbar.setAttribute('role', 'toolbar');\n\t\tthis.graphView.toolbar.setAttribute('aria-label', 'Frame graph view controls');\n\n\t\tthis.declarationsButton = createToolbarButton('Declarations', 'Show resource declaration nodes', () => this.toggleDeclarations());\n\t\tthis.groupsButton = createToolbarButton('Groups', 'Toggle diagnostic group projection', () => this.toggleGroups());\n\t\tthis.collapseGroupsButton = createToolbarButton('Collapse All', 'Collapse every diagnostic group', () => this.collapseAllGroups());\n\n\t\tconst actionControls = document.createElement('div');\n\t\tactionControls.className = 'zenfg-inspector-graph-action-controls';\n\t\tactionControls.append(\n\t\t\tthis.declarationsButton,\n\t\t\tthis.groupsButton,\n\t\t\tthis.collapseGroupsButton,\n\t\t\tcreateToolbarButton('Fit', 'Fit graph to view', () => fitGraph(this.graphView)),\n\t\t);\n\t\tthis.graphView.toolbar.append(actionControls);\n\n\t\tconst callbacks: WorkbenchCallbacks = {\n\t\t\tonSelect: (selection) => this.handleSelect(selection),\n\t\t\tonHover: (selection) => this.handleHover(selection),\n\t\t\tonGroupToggle: (pathKey) => this.toggleGroup(pathKey),\n\t\t\tisGroupExpanded: (pathKey) => this.graphView.expandedGroupPaths.has(pathKey),\n\t\t\tonReveal: (selection, tab) => this.handleReveal(selection, tab),\n\t\t\tonNavigate: (tab, filter) => this.workbench.navigate(tab, filter),\n\t\t};\n\t\tthis.workbench = new FrameGraphDebugWorkbench(this.graphView, callbacks, {\n\t\t\tonCapture: () => { void this.captureSnapshot(); },\n\t\t\tonImport: (file) => { void this.importSnapshot(file); },\n\t\t\tonDownload: () => this.downloadSnapshot(),\n\t\t\tonCopyJson: () => { void this.copySnapshotJson(); },\n\t\t}, {\n\t\t\tbranding,\n\t\t\tidPrefix: this.dom.id,\n\t\t});\n\t\tthis.content.append(this.workbench.root);\n\t\tthis.body.appendChild(this.content);\n\t\tthis.dom.append(this.body, this.dropOverlay);\n\t\tthis.dom.addEventListener('dragenter', this.handleDragEnter);\n\t\tthis.dom.addEventListener('dragover', this.handleDragOver);\n\t\tthis.dom.addEventListener('dragleave', this.handleDragLeave);\n\t\tthis.dom.addEventListener('dragend', this.handleDragEnd);\n\t\tthis.dom.addEventListener('drop', this.handleDrop);\n\t\tthis.updateCaptureActions();\n\t\tthis.updateGraphControls();\n\t\tthis.showEmptyState();\n\t\tif (options.theme) this.setTheme(options.theme);\n\t\tqueueMicrotask(() => { if (!this.destroyed) { this.refreshTheme(); this.maybeAutoCapture(); } });\n\t}\n\n /** Replace API-applied variables on this instance, then synchronize graph styles.\n * Pass null to restore host CSS and defaults. Does not change capture or interaction state.\n */\n setTheme(theme: InspectorTheme | null): void {\n if (this.destroyed) return;\n this.themeController.apply(theme);\n this.refreshTheme();\n }\n\n /** Re-read final CSS values after external CSS changes and refresh graph and legend.\n * Does not write theme variables, recapture, fit, or rebuild the component.\n */\n refreshTheme(): void {\n if (this.destroyed) return;\n const theme = resolveGraphTheme(this.dom);\n this.graphView.theme = theme;\n this.graphView.renderer?.setTheme?.(theme);\n if (this.viewModel) renderGraphLegend(this.graphView.legend, this.viewModel, theme, this.graphView.showResourceDeclarations);\n }\n\n\t/**\n\t * Replaces or removes the live-capture provider.\n\t *\n\t * @remarks Installing a provider may immediately begin an asynchronous\n\t * capture when no snapshot is displayed. Replacing or removing a provider\n\t * invalidates its pending capture results without cancelling the provider\n\t * promise. An already displayed snapshot and any pending import are preserved.\n\t */\n\tsetCaptureSnapshotProvider(provider: FrameGraphInspectorOptions['captureSnapshot']): void {\n\t\tif (this.destroyed || this.captureSnapshotCallback === provider) return;\n\t\tif (this.capturing) {\n\t\t\tthis.operationRevision += 1;\n\t\t\tthis.capturing = false;\n\t\t}\n\t\tthis.captureSnapshotCallback = provider;\n\t\tif (!this.viewModel) this.initialAutoCaptureAttempted = false;\n\t\tif (!provider && !this.viewModel && !this.importing) this.showEmptyState();\n\t\tthis.updateCaptureActions();\n\t\tthis.maybeAutoCapture();\n\t}\n\n\t/**\n\t * Requests and displays a live snapshot from the configured provider.\n\t *\n\t * @remarks Concurrent requests are coalesced. Provider errors, invalid\n\t * snapshots, and an unavailable provider are displayed in the inspector and\n\t * do not reject the returned promise.\n\t */\n\tasync captureSnapshot(): Promise<void> {\n\t\tif (this.destroyed || this.capturing) return;\n\t\tif (!this.captureSnapshotCallback) {\n\t\t\tthis.reportCaptureIssue('Waiting for a FrameGraph capture source.');\n\t\t\treturn;\n\t\t}\n\t\tconst revision = ++this.operationRevision;\n\t\tthis.importing = false;\n\t\tthis.capturing = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tif (!this.viewModel) this.workbench.showEmptyState('capturing', 'Capturing the next rendered frame…');\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tconst request: FrameGraphCaptureRequest = { timing: 'both' };\n\t\t\tconst snapshot = await this.captureSnapshotCallback(request);\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tif (!snapshot) {\n\t\t\t\tthis.reportCaptureIssue('No snapshot was produced. Capture again when rendering is active.');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst decoded = decodeFrameGraphSnapshot(snapshot);\n\t\t\tif (!decoded.ok) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to capture FrameGraph: ${formatIssues(decoded.issues)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.applySnapshot(decoded.snapshot, { kind: 'live', label: 'Live Capture' });\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to capture FrameGraph: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\tif (revision === this.operationRevision) this.capturing = false;\n\t\t\tif (!this.destroyed && revision === this.operationRevision) this.updateCaptureActions();\n\t\t}\n\t}\n\n\t/**\n\t * Validates and synchronously displays a programmatic Snapshot 1.2 value.\n\t *\n\t * @throws {@link @zenfg/snapshot!index.FrameGraphSnapshotValidationError | FrameGraphSnapshotValidationError} if `snapshot` is invalid.\n\t */\n\tsetSnapshot(snapshot: FrameGraphSnapshot): void {\n\t\tif (this.destroyed) return;\n\t\tthis.operationRevision += 1;\n\t\tthis.capturing = false;\n\t\tthis.importing = false;\n\t\tconst decoded = decodeFrameGraphSnapshot(snapshot);\n\t\tif (!decoded.ok) throw new FrameGraphSnapshotValidationError(decoded.issues);\n\t\tthis.applySnapshot(decoded.snapshot, { kind: 'programmatic', label: 'Programmatic' });\n\t}\n\n\t/** Returns the currently displayed canonical snapshot, if any. */\n\tgetSnapshot(): FrameGraphSnapshot | undefined {\n\t\treturn this.protocolSnapshot;\n\t}\n\n\t/**\n\t * Reads, migrates, validates, and displays a snapshot JSON file.\n\t *\n\t * @remarks Files above `maxImportBytes`, read failures, invalid JSON, and\n\t * validation failures are displayed in the UI and do not reject the promise.\n\t */\n\tasync importSnapshot(file: File): Promise<void> {\n\t\tif (this.destroyed) return;\n\t\tconst revision = ++this.operationRevision;\n\t\tthis.capturing = false;\n\t\tthis.importing = false;\n\t\tif (file.size > this.maxImportBytes) {\n\t\t\tthis.reportCaptureIssue(`Import exceeds the ${formatImportLimit(this.maxImportBytes)} limit.`);\n\t\t\treturn;\n\t\t}\n\t\tthis.importing = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tconst text = await file.text();\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tconst decoded = parseFrameGraphSnapshot(text);\n\t\t\tif (!decoded.ok) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to import snapshot: ${formatIssues(decoded.issues)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.applySnapshot(decoded.snapshot, {\n\t\t\t\tkind: 'file',\n\t\t\t\tlabel: file.name || 'Imported JSON',\n\t\t\t});\n\t\t\tconst sourceFormat = decoded.snapshot.capture.migration?.sourceFormat;\n\t\t\tif (sourceFormat) {\n\t\t\t\t// The current import format can differ from retained historical provenance.\n\t\t\t\tconst sourceLabel = {\n\t\t\t\t\t'legacy-v0': 'Legacy V0',\n\t\t\t\t\t'legacy-candidate-v1': 'Legacy Candidate V1',\n\t\t\t\t\t'snapshot-v1.1': 'Snapshot 1.1',\n\t\t\t\t}[decoded.migrated && decoded.source !== 'v1' ? decoded.source : sourceFormat];\n\t\t\t\tconst version = decoded.snapshot.version;\n\t\t\t\tconst targetLabel = `Snapshot ${version.major}.${version.minor}`;\n\t\t\t\tthis.statusMessage = decoded.migrated\n\t\t\t\t\t? `Imported ${sourceLabel} and migrated it to ZenFG ${targetLabel}.`\n\t\t\t\t\t: `Imported ${targetLabel} with ${sourceLabel} migration provenance.`;\n\t\t\t\tthis.statusTone = 'neutral';\n\t\t\t}\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to import snapshot: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\tif (revision === this.operationRevision) this.importing = false;\n\t\t\tif (!this.destroyed && revision === this.operationRevision) this.updateCaptureActions();\n\t\t}\n\t}\n\n\t/** Downloads the displayed snapshot as pretty-printed canonical JSON. */\n\tdownloadSnapshot(): void {\n\t\tif (this.destroyed || !this.protocolSnapshot) return;\n\t\tconst json = stringifyFrameGraphSnapshot(this.protocolSnapshot, { pretty: true });\n\t\tconst url = URL.createObjectURL(new Blob([json], { type: 'application/json;charset=utf-8' }));\n\t\tconst anchor = document.createElement('a');\n\t\tanchor.href = url;\n\t\tanchor.download = `frame-graph-${this.protocolSnapshot.capture.frameIndex}.fgsnapshot.json`;\n\t\tanchor.click();\n\t\tURL.revokeObjectURL(url);\n\t}\n\n\t/**\n\t * Copies the displayed snapshot as pretty-printed canonical JSON.\n\t *\n\t * @remarks Clipboard failures are shown in the UI and do not reject the\n\t * returned promise. A legacy `document.execCommand` fallback is used when the\n\t * async Clipboard API is unavailable.\n\t */\n\tasync copySnapshotJson(): Promise<void> {\n\t\tif (this.destroyed || this.copying || !this.protocolSnapshot) return;\n\t\tconst snapshot = this.protocolSnapshot;\n\t\tconst revision = this.operationRevision;\n\t\tthis.copying = true;\n\t\tthis.copied = false;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tawait writeTextToClipboard(stringifyFrameGraphSnapshot(snapshot, { pretty: true }));\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tthis.copied = true;\n\t\t\tif (this.copyFeedbackTimeout !== undefined) window.clearTimeout(this.copyFeedbackTimeout);\n\t\t\tthis.copyFeedbackTimeout = window.setTimeout(() => {\n\t\t\t\tthis.copied = false;\n\t\t\t\tthis.copyFeedbackTimeout = undefined;\n\t\t\t\tthis.updateCaptureActions();\n\t\t\t}, 1200);\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.statusMessage = `Failed to copy snapshot: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\t}\n\t\t\tconsole.warn('Failed to copy FrameGraph Snapshot.', error);\n\t\t}\n\t\tfinally {\n\t\t\tthis.copying = false;\n\t\t\tif (!this.destroyed) this.updateCaptureActions();\n\t\t}\n\t}\n\n\tprivate applySnapshot(snapshot: FrameGraphSnapshot, source: FrameGraphDebugSnapshotSource): void {\n\t\tconst viewModel = createDebugViewModel(snapshot, source);\n\t\tthis.copied = false;\n\t\tif (this.copyFeedbackTimeout !== undefined) {\n\t\t\twindow.clearTimeout(this.copyFeedbackTimeout);\n\t\t\tthis.copyFeedbackTimeout = undefined;\n\t\t}\n\t\tthis.protocolSnapshot = snapshot;\n\t\tthis.viewModel = viewModel;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.graphView.captureRevision = (this.graphView.captureRevision ?? 0) + 1;\n\t\tthis.graphView.revealOnNextRender = undefined;\n\t\tthis.graphView.renderer?.cancelReveal?.();\n\t\tthis.hovered = undefined;\n\t\tthis.initialAutoCaptureAttempted = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tif (this.selected?.kind === 'node' || this.selected?.kind === 'culled') this.selected = resolveNodeSelection(viewModel, this.selected.id);\n\t\telse if (this.selected && !selectionExists(viewModel, this.selected)) this.selected = undefined;\n\t\tthis.workbench.setSnapshot(viewModel, this.selected);\n\t\tthis.updateCaptureActions();\n\t\tthis.updateGraphControls();\n\t}\n\n\t/**\n\t * Idempotently cancels pending UI results, releases graph resources, and\n\t * removes the inspector workbench. Do not reuse the controller afterward.\n\t */\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\t\tthis.operationRevision += 1;\n\t\tif (this.copyFeedbackTimeout !== undefined) window.clearTimeout(this.copyFeedbackTimeout);\n\t\tthis.clearDropState();\n\t\tthis.dom.removeEventListener('dragenter', this.handleDragEnter);\n\t\tthis.dom.removeEventListener('dragover', this.handleDragOver);\n\t\tthis.dom.removeEventListener('dragleave', this.handleDragLeave);\n\t\tthis.dom.removeEventListener('dragend', this.handleDragEnd);\n\t\tthis.dom.removeEventListener('drop', this.handleDrop);\n\t\tthis.themeController.destroy();\n\t\tdestroyGraph(this.graphView);\n\t\tthis.workbench.destroy();\n\t\tthis.dom.remove();\n\t}\n\n\tprivate updateCaptureActions(): void {\n\t\tthis.workbench.setSnapshotActionState({\n\t\t\tproviderAvailable: Boolean(this.captureSnapshotCallback),\n\t\t\thasCapture: Boolean(this.viewModel),\n\t\t\tcapturing: this.capturing,\n\t\t\timporting: this.importing,\n\t\t\tcopying: this.copying,\n\t\t\tcopied: this.copied,\n\t\t\tmessage: this.viewModel ? this.statusMessage : undefined,\n\t\t\tmessageTone: this.statusTone,\n\t\t});\n\t}\n\n\tprivate maybeAutoCapture(): void {\n\t\tif (\n\t\t\tthis.destroyed\n\t\t\t|| this.viewModel\n\t\t\t|| this.initialAutoCaptureAttempted\n\t\t\t|| this.capturing\n\t\t\t|| this.importing\n\t\t\t|| !this.captureSnapshotCallback\n\t\t) return;\n\t\tthis.initialAutoCaptureAttempted = true;\n\t\tvoid this.captureSnapshot();\n\t}\n\tprivate handleSelect(selection: Selection): void {\n\t\tif (!this.viewModel || !selectionExists(this.viewModel, selection)) return;\n\t\tthis.selected = selection;\n\t\tthis.workbench.setSelection(selection);\n\t}\n\n\tprivate handleReveal(selection: Selection, tab: WorkbenchTab): void {\n\t\tconst snapshot = this.viewModel;\n\t\tif (!snapshot || !selectionExists(snapshot, selection)) return;\n\t\tif (tab === 'graph') {\n\t\t\tconst expanded = new Set(this.graphView.expandedGroupPaths);\n\t\t\tconst groupsEnabled = this.graphView.groupsEnabled;\n\t\t\tconst showResourceDeclarations = this.graphView.showResourceDeclarations;\n\t\t\tif (selection.kind === 'resource') this.graphView.showResourceDeclarations = true;\n\t\t\tif (selection.kind === 'group') this.graphView.groupsEnabled = true;\n\t\t\tlet groupId: string | undefined;\n\t\t\tif (selection.kind === 'node') groupId = snapshot.nodeById.get(selection.id)?.debugGroupId;\n\t\t\telse if (selection.kind === 'resource') groupId = snapshot.resourceById.get(selection.id)?.debugGroupId;\n\t\t\telse if (selection.kind === 'group') groupId = snapshot.groupByPathKey.get(selection.pathKey)?.parentId;\n\t\t\tif (this.graphView.groupsEnabled && groupId) {\n\t\t\t\tfor (const id of snapshot.groupById.get(groupId)?.ancestorIds ?? []) {\n\t\t\t\t\tconst group = snapshot.groupById.get(id);\n\t\t\t\t\tif (group) this.graphView.expandedGroupPaths.add(group.pathKey);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst scene = resolveGraphScene(this.graphView, snapshot);\n\t\t\tconst availableIds = new Set([...scene.nodes, ...scene.edges].map((entry) => entry.id));\n\t\t\tif (!(scene.interaction.primaryElementIdsBySelection.get(selectionKey(selection))?.some((id) => availableIds.has(id)))) {\n\t\t\t\tthis.graphView.groupsEnabled = groupsEnabled;\n\t\t\t\tthis.graphView.showResourceDeclarations = showResourceDeclarations;\n\t\t\t\tthis.graphView.expandedGroupPaths.clear();\n\t\t\t\tfor (const path of expanded) this.graphView.expandedGroupPaths.add(path);\n\t\t\t\tthis.workbench.showNavigationIssue(selection.kind === 'culled' ? 'Culled passes are not part of Frame Flow.' : 'This object has no representation in Frame Flow.', selection);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.graphView.revealOnNextRender = { selection, revision: ++this.revealRevision };\n\t\t\tthis.updateGraphControls();\n\t\t}\n\t\tthis.handleSelect(selection);\n\t\tthis.workbench.reveal(selection, tab);\n\t}\n\n\tprivate handleHover(selection: Selection | undefined): void {\n\t\tif (!this.viewModel || sameSelection(this.hovered, selection)) return;\n\t\tthis.hovered = selection;\n\t\tthis.workbench.setHovered(selection);\n\t}\n\n\tprivate updateGraphControls(): void {\n\t\tconst showDeclarations = this.graphView.showResourceDeclarations ?? true;\n\t\tthis.declarationsButton.classList.toggle('active', showDeclarations);\n\t\tthis.declarationsButton.setAttribute('aria-pressed', String(showDeclarations));\n\t\tconst hasGroups = (this.viewModel?.debugGroups.length ?? 0) > 0;\n\t\tthis.groupsButton.disabled = !hasGroups;\n\t\tthis.groupsButton.hidden = !hasGroups;\n\t\tthis.collapseGroupsButton.hidden = !hasGroups;\n\t\tthis.groupsButton.classList.toggle('active', hasGroups && this.graphView.groupsEnabled);\n\t\tthis.groupsButton.setAttribute('aria-pressed', hasGroups && this.graphView.groupsEnabled ? 'true' : 'false');\n\t\tconst hasExpanded = this.viewModel?.debugGroups.some((group) => this.graphView.expandedGroupPaths.has(group.pathKey)) ?? false;\n\t\tthis.collapseGroupsButton.disabled = !hasGroups || !this.graphView.groupsEnabled || !hasExpanded;\n\t}\n\n\tprivate toggleDeclarations(): void {\n\t\tthis.handleHover(undefined);\n\t\tthis.graphView.showResourceDeclarations = !(this.graphView.showResourceDeclarations ?? true);\n\t\tthis.graphView.renderer?.cancelReveal?.();\n\t\tthis.graphView.revealOnNextRender = undefined;\n\t\tthis.graphView.anchorElementIdOnNextRender = undefined;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate toggleGroups(): void {\n\t\tif (!this.viewModel?.debugGroups.length) return;\n\t\tthis.handleHover(undefined);\n\t\tthis.graphView.groupsEnabled = !this.graphView.groupsEnabled;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate toggleGroup(pathKey: string): void {\n\t\tthis.handleHover(undefined);\n\t\tif (this.graphView.expandedGroupPaths.has(pathKey)) this.graphView.expandedGroupPaths.delete(pathKey);\n\t\telse this.graphView.expandedGroupPaths.add(pathKey);\n\t\tthis.graphView.anchorElementIdOnNextRender = graphGroupElementId(pathKey);\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate collapseAllGroups(): void {\n\t\tif (this.graphView.expandedGroupPaths.size === 0) return;\n\t\tthis.handleHover(undefined);\n\t\tthis.graphView.expandedGroupPaths.clear();\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate showEmptyState(): void {\n\t\tconst providerAvailable = Boolean(this.captureSnapshotCallback);\n\t\tthis.workbench.showEmptyState(\n\t\t\t'empty',\n\t\t\tproviderAvailable\n\t\t\t\t? 'No capture yet. Use Capture to request the next rendered frame.'\n\t\t\t\t: 'Drop a ZenFG Snapshot here or choose Import.',\n\t\t\tproviderAvailable ? undefined : 'Files are processed locally in your browser.',\n\t\t);\n\t}\n\n\tprivate setDropActive(active: boolean): void {\n\t\tif (this.destroyed) return;\n\t\tthis.dropOverlay.hidden = !active;\n\t\tthis.dom.classList.toggle('drop-active', active);\n\t}\n\n\tprivate clearDropState(): void {\n\t\tthis.dragDepth = 0;\n\t\tthis.dropOverlay.hidden = true;\n\t\tthis.dom.classList.remove('drop-active');\n\t}\n\n\tprivate reportCaptureIssue(message: string): void {\n\t\tthis.statusMessage = message;\n\t\tthis.statusTone = 'error';\n\t\tif (!this.viewModel) this.workbench.showEmptyState('error', message);\n\t\tthis.updateCaptureActions();\n\t}\n}\n\n/**\n * Creates an inspector, appends its root element to `host`, and returns its\n * lifecycle controller.\n *\n * @throws If inspector construction fails; see {@link FrameGraphInspector}.\n */\nexport function mountFrameGraphInspector(host: HTMLElement, options?: FrameGraphInspectorOptions): FrameGraphInspector {\n\tconst inspector = new FrameGraphInspector(options);\n\thost.appendChild(inspector.dom);\n\tinspector.refreshTheme();\n\treturn inspector;\n}\n\nasync function writeTextToClipboard(text: string): Promise<void> {\n\tif (navigator.clipboard?.writeText) {\n\t\tawait navigator.clipboard.writeText(text);\n\t\treturn;\n\t}\n\tconst textArea = document.createElement('textarea');\n\ttextArea.value = text;\n\ttextArea.setAttribute('readonly', 'true');\n\ttextArea.style.position = 'fixed';\n\ttextArea.style.left = '-9999px';\n\ttextArea.style.top = '0';\n\tdocument.body.appendChild(textArea);\n\ttextArea.select();\n\ttry {\n\t\tif (!document.execCommand('copy')) throw new Error('document.execCommand(\"copy\") returned false.');\n\t}\n\tfinally {\n\t\ttextArea.remove();\n\t}\n}\n\nfunction normalizeMaxImportBytes(value: number | undefined): number {\n\treturn normalizeLimit(value, DEFAULT_MAX_IMPORT_BYTES, 'maxImportBytes');\n}\n\nfunction normalizeLimit(value: number | undefined, fallback: number, name: string): number {\n\tif (value === undefined) return fallback;\n\tif (!Number.isSafeInteger(value) || value < 0) {\n\t\tthrow new Error(`${name} must be a non-negative safe integer.`);\n\t}\n\treturn value;\n}\n\nfunction formatImportLimit(bytes: number): string {\n\treturn bytes >= 1024 * 1024 && bytes % (1024 * 1024) === 0\n\t\t? `${bytes / (1024 * 1024)} MiB`\n\t\t: `${bytes} bytes`;\n}\n\nfunction formatIssues(issues: readonly { readonly path: string; readonly message: string }[]): string {\n\treturn issues.map((issue) => `${issue.path || '/'}: ${issue.message}`).join('\\n');\n}\n\nfunction isFileDrag(event: DragEvent): boolean {\n\treturn Array.from(event.dataTransfer?.types ?? []).includes('Files');\n}\n\nlet nextInspectorId = 0;\nfunction createInspectorId(): string {\n\tnextInspectorId += 1;\n\treturn `zenfg-inspector-${nextInspectorId}`;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,MAAM,MAAM,wBAAwB,GAAG;IACtC,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;CACxC,CAAC"}
|
package/dist/capture.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"","sourcesContent":["/** Requested timing families for the next live capture; never changes imported data. */\nexport type FrameGraphCaptureRequest = {\n\treadonly timing: 'cpu' | 'gpu' | 'both';\n};\n"]}
|
|
@@ -34,6 +34,7 @@ export type FrameGraphDebugNode = {
|
|
|
34
34
|
readonly sideEffect: boolean;
|
|
35
35
|
readonly debugGroupId?: string;
|
|
36
36
|
readonly gpuDurationMicros?: number;
|
|
37
|
+
readonly cpuDurationMicros?: number;
|
|
37
38
|
readonly reads: readonly FrameGraphDebugAccess[];
|
|
38
39
|
readonly writes: readonly FrameGraphDebugAccess[];
|
|
39
40
|
};
|
|
@@ -87,6 +88,8 @@ export type FrameGraphDebugGroupSummary = {
|
|
|
87
88
|
readonly externalSubmissionCount: number;
|
|
88
89
|
readonly gpuWorkDurationMicros: number;
|
|
89
90
|
readonly timedNodeCount: number;
|
|
91
|
+
readonly cpuTimedNodeCount: number;
|
|
92
|
+
readonly cpuWorkDurationMicros: number;
|
|
90
93
|
readonly timingEligibleNodeCount: number;
|
|
91
94
|
};
|
|
92
95
|
export type FrameGraphDebugGroup = {
|
|
@@ -104,12 +107,23 @@ export type FrameGraphDebugGroup = {
|
|
|
104
107
|
export type FrameGraphDebugMetrics = {
|
|
105
108
|
readonly timingEligibleNodeCount: number;
|
|
106
109
|
readonly timedNodeCount: number;
|
|
110
|
+
readonly cpuTimedNodeCount: number;
|
|
111
|
+
readonly cpuWorkDurationMicros: number;
|
|
107
112
|
readonly slowestNode?: FrameGraphDebugNode;
|
|
108
113
|
readonly transientEstimatedByteSize?: number;
|
|
109
114
|
readonly logicalCapacityBytes?: number;
|
|
110
115
|
readonly physicalEstimatedBytes?: number;
|
|
111
116
|
readonly aliasReuseBytes?: number;
|
|
112
117
|
readonly aliasedAllocationCount: number;
|
|
118
|
+
readonly estimatedCoverage: {
|
|
119
|
+
readonly transient: EstimateCoverage;
|
|
120
|
+
readonly logical: EstimateCoverage;
|
|
121
|
+
readonly physical: EstimateCoverage;
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
export type EstimateCoverage = {
|
|
125
|
+
readonly known: number;
|
|
126
|
+
readonly total: number;
|
|
113
127
|
};
|
|
114
128
|
export type FrameGraphDebugSnapshotSource = {
|
|
115
129
|
readonly kind: 'live' | 'file' | 'programmatic';
|
|
@@ -131,6 +145,10 @@ export type FrameGraphDebugViewModel = {
|
|
|
131
145
|
readonly executionSegments: readonly FrameGraphDebugExecutionSegment[];
|
|
132
146
|
readonly textureViewById: ReadonlyMap<string, FrameGraphSnapshot['graph']['textureViews'][number]>;
|
|
133
147
|
readonly nodeById: ReadonlyMap<string, FrameGraphDebugNode>;
|
|
148
|
+
readonly canonicalNodeById: ReadonlyMap<string, FrameGraphSnapshot['graph']['nodes'][number]>;
|
|
149
|
+
readonly culledById: ReadonlyMap<string, FrameGraphDebugCulledNode>;
|
|
150
|
+
readonly diagnosticsByNodeId: ReadonlyMap<string, readonly FrameGraphSnapshot['diagnostics'][number][]>;
|
|
151
|
+
readonly diagnosticsByResourceId: ReadonlyMap<string, readonly FrameGraphSnapshot['diagnostics'][number][]>;
|
|
134
152
|
readonly resourceById: ReadonlyMap<string, FrameGraphDebugResource>;
|
|
135
153
|
readonly groupById: ReadonlyMap<string, FrameGraphDebugGroup>;
|
|
136
154
|
readonly groupByPathKey: ReadonlyMap<string, FrameGraphDebugGroup>;
|
|
@@ -140,6 +158,7 @@ export type FrameGraphDebugViewModel = {
|
|
|
140
158
|
readonly segmentByNodeId: ReadonlyMap<string, FrameGraphDebugExecutionSegment>;
|
|
141
159
|
readonly segmentByIndex: ReadonlyMap<number, FrameGraphDebugExecutionSegment>;
|
|
142
160
|
readonly metrics: FrameGraphDebugMetrics;
|
|
161
|
+
readonly cpuProfiling: FrameGraphSnapshot['timings']['cpu'];
|
|
143
162
|
readonly profiling: {
|
|
144
163
|
readonly status: 'available';
|
|
145
164
|
readonly frameIndex: number;
|