@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.
Files changed (172) hide show
  1. package/GUIDE.md +182 -0
  2. package/README.md +61 -89
  3. package/THEMING.md +124 -0
  4. package/dist/FrameGraphInspector.d.ts +23 -4
  5. package/dist/FrameGraphInspector.d.ts.map +1 -1
  6. package/dist/FrameGraphInspector.js +137 -29
  7. package/dist/FrameGraphInspector.js.map +1 -1
  8. package/dist/capture.d.ts +5 -0
  9. package/dist/capture.d.ts.map +1 -0
  10. package/dist/capture.js +2 -0
  11. package/dist/capture.js.map +1 -0
  12. package/dist/debugCaptureModel.d.ts +19 -0
  13. package/dist/debugCaptureModel.d.ts.map +1 -1
  14. package/dist/debugCaptureModel.js +36 -2
  15. package/dist/debugCaptureModel.js.map +1 -1
  16. package/dist/index.d.ts +2 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/panelAliasAnalysis.d.ts +1 -0
  20. package/dist/panelAliasAnalysis.d.ts.map +1 -1
  21. package/dist/panelAliasAnalysis.js +23 -54
  22. package/dist/panelAliasAnalysis.js.map +1 -1
  23. package/dist/panelCytoscapeGraphRenderer.d.ts +15 -2
  24. package/dist/panelCytoscapeGraphRenderer.d.ts.map +1 -1
  25. package/dist/panelCytoscapeGraphRenderer.js +145 -23
  26. package/dist/panelCytoscapeGraphRenderer.js.map +1 -1
  27. package/dist/panelDetailLayout.d.ts +27 -0
  28. package/dist/panelDetailLayout.d.ts.map +1 -0
  29. package/dist/panelDetailLayout.js +174 -0
  30. package/dist/panelDetailLayout.js.map +1 -0
  31. package/dist/panelDetailStyles.d.ts +2 -0
  32. package/dist/panelDetailStyles.d.ts.map +1 -0
  33. package/dist/panelDetailStyles.js +57 -0
  34. package/dist/panelDetailStyles.js.map +1 -0
  35. package/dist/panelDiagnosticsView.d.ts +10 -1
  36. package/dist/panelDiagnosticsView.d.ts.map +1 -1
  37. package/dist/panelDiagnosticsView.js +166 -57
  38. package/dist/panelDiagnosticsView.js.map +1 -1
  39. package/dist/panelDomHelpers.d.ts.map +1 -1
  40. package/dist/panelDomHelpers.js +6 -5
  41. package/dist/panelDomHelpers.js.map +1 -1
  42. package/dist/panelGraphLayout.d.ts +3 -2
  43. package/dist/panelGraphLayout.d.ts.map +1 -1
  44. package/dist/panelGraphLayout.js +6 -5
  45. package/dist/panelGraphLayout.js.map +1 -1
  46. package/dist/panelGraphRenderer.d.ts +10 -0
  47. package/dist/panelGraphRenderer.d.ts.map +1 -1
  48. package/dist/panelGraphRenderer.js.map +1 -1
  49. package/dist/panelGraphScene.d.ts +1 -0
  50. package/dist/panelGraphScene.d.ts.map +1 -1
  51. package/dist/panelGraphScene.js +69 -32
  52. package/dist/panelGraphScene.js.map +1 -1
  53. package/dist/panelGraphSearch.d.ts +16 -0
  54. package/dist/panelGraphSearch.d.ts.map +1 -0
  55. package/dist/panelGraphSearch.js +93 -0
  56. package/dist/panelGraphSearch.js.map +1 -0
  57. package/dist/panelGraphView.d.ts +82 -0
  58. package/dist/panelGraphView.d.ts.map +1 -1
  59. package/dist/panelGraphView.js +15 -4
  60. package/dist/panelGraphView.js.map +1 -1
  61. package/dist/panelGraphVisuals.d.ts +14 -6
  62. package/dist/panelGraphVisuals.d.ts.map +1 -1
  63. package/dist/panelGraphVisuals.js +126 -51
  64. package/dist/panelGraphVisuals.js.map +1 -1
  65. package/dist/panelInspectorView.d.ts +8 -0
  66. package/dist/panelInspectorView.d.ts.map +1 -1
  67. package/dist/panelInspectorView.js +242 -48
  68. package/dist/panelInspectorView.js.map +1 -1
  69. package/dist/panelListStyles.d.ts +3 -0
  70. package/dist/panelListStyles.d.ts.map +1 -0
  71. package/dist/panelListStyles.js +155 -0
  72. package/dist/panelListStyles.js.map +1 -0
  73. package/dist/panelMemoryStyles.d.ts +3 -0
  74. package/dist/panelMemoryStyles.d.ts.map +1 -0
  75. package/dist/panelMemoryStyles.js +42 -0
  76. package/dist/panelMemoryStyles.js.map +1 -0
  77. package/dist/panelMemoryView.d.ts +13 -1
  78. package/dist/panelMemoryView.d.ts.map +1 -1
  79. package/dist/panelMemoryView.js +161 -41
  80. package/dist/panelMemoryView.js.map +1 -1
  81. package/dist/panelPassesView.d.ts +15 -0
  82. package/dist/panelPassesView.d.ts.map +1 -1
  83. package/dist/panelPassesView.js +202 -72
  84. package/dist/panelPassesView.js.map +1 -1
  85. package/dist/panelRawView.d.ts +15 -0
  86. package/dist/panelRawView.d.ts.map +1 -0
  87. package/dist/panelRawView.js +105 -0
  88. package/dist/panelRawView.js.map +1 -0
  89. package/dist/panelResourcesView.d.ts +8 -0
  90. package/dist/panelResourcesView.d.ts.map +1 -1
  91. package/dist/panelResourcesView.js +62 -31
  92. package/dist/panelResourcesView.js.map +1 -1
  93. package/dist/panelSelection.d.ts +9 -1
  94. package/dist/panelSelection.d.ts.map +1 -1
  95. package/dist/panelSelection.js +34 -4
  96. package/dist/panelSelection.js.map +1 -1
  97. package/dist/panelTheme.d.ts +13 -0
  98. package/dist/panelTheme.d.ts.map +1 -0
  99. package/dist/panelTheme.js +104 -0
  100. package/dist/panelTheme.js.map +1 -0
  101. package/dist/panelTypes.d.ts +10 -1
  102. package/dist/panelTypes.d.ts.map +1 -1
  103. package/dist/panelTypes.js.map +1 -1
  104. package/dist/panelVisualTheme.d.ts +147 -50
  105. package/dist/panelVisualTheme.d.ts.map +1 -1
  106. package/dist/panelVisualTheme.js +34 -44
  107. package/dist/panelVisualTheme.js.map +1 -1
  108. package/dist/panelWorkbenchHelpers.d.ts +12 -1
  109. package/dist/panelWorkbenchHelpers.d.ts.map +1 -1
  110. package/dist/panelWorkbenchHelpers.js +62 -1
  111. package/dist/panelWorkbenchHelpers.js.map +1 -1
  112. package/dist/panelWorkbenchStyles.d.ts +2 -0
  113. package/dist/panelWorkbenchStyles.d.ts.map +1 -0
  114. package/dist/panelWorkbenchStyles.js +101 -0
  115. package/dist/panelWorkbenchStyles.js.map +1 -0
  116. package/dist/panelWorkbenchView.d.ts +16 -0
  117. package/dist/panelWorkbenchView.d.ts.map +1 -1
  118. package/dist/panelWorkbenchView.js +228 -50
  119. package/dist/panelWorkbenchView.js.map +1 -1
  120. package/dist/query.js.map +1 -1
  121. package/dist/styles.d.ts.map +1 -1
  122. package/dist/styles.js +147 -195
  123. package/dist/styles.js.map +1 -1
  124. package/dist/theme.d.ts +22 -0
  125. package/dist/theme.d.ts.map +1 -0
  126. package/dist/theme.js +10 -0
  127. package/dist/theme.js.map +1 -0
  128. package/dist/themeDefinitions.d.ts +251 -0
  129. package/dist/themeDefinitions.d.ts.map +1 -0
  130. package/dist/themeDefinitions.js +96 -0
  131. package/dist/themeDefinitions.js.map +1 -0
  132. package/dist/themePalette.d.ts +66 -0
  133. package/dist/themePalette.d.ts.map +1 -0
  134. package/dist/themePalette.js +37 -0
  135. package/dist/themePalette.js.map +1 -0
  136. package/dist/themes.css +165 -0
  137. package/package.json +44 -10
  138. package/src/FrameGraphInspector.ts +130 -31
  139. package/src/capture.ts +4 -0
  140. package/src/debugCaptureModel.ts +53 -2
  141. package/src/index.ts +6 -2
  142. package/src/panelAliasAnalysis.ts +24 -70
  143. package/src/panelCytoscapeGraphRenderer.ts +140 -23
  144. package/src/panelDetailLayout.ts +155 -0
  145. package/src/panelDetailStyles.ts +56 -0
  146. package/src/panelDiagnosticsView.ts +166 -85
  147. package/src/panelDomHelpers.ts +4 -5
  148. package/src/panelGraphLayout.ts +6 -5
  149. package/src/panelGraphRenderer.ts +7 -0
  150. package/src/panelGraphScene.ts +68 -30
  151. package/src/panelGraphSearch.ts +96 -0
  152. package/src/panelGraphView.ts +14 -4
  153. package/src/panelGraphVisuals.ts +122 -52
  154. package/src/panelInspectorView.ts +227 -48
  155. package/src/panelListStyles.ts +154 -0
  156. package/src/panelMemoryStyles.ts +41 -0
  157. package/src/panelMemoryView.ts +178 -53
  158. package/src/panelPassesView.ts +190 -137
  159. package/src/panelRawView.ts +99 -0
  160. package/src/panelResourcesView.ts +69 -56
  161. package/src/panelSelection.ts +37 -5
  162. package/src/panelTheme.ts +85 -0
  163. package/src/panelTypes.ts +7 -1
  164. package/src/panelVisualTheme.ts +38 -49
  165. package/src/panelWorkbenchHelpers.ts +60 -2
  166. package/src/panelWorkbenchStyles.ts +100 -0
  167. package/src/panelWorkbenchView.ts +201 -52
  168. package/src/query.ts +11 -11
  169. package/src/styles.ts +148 -195
  170. package/src/theme.ts +24 -0
  171. package/src/themeDefinitions.ts +103 -0
  172. package/src/themePalette.ts +44 -0
@@ -1,39 +1,40 @@
1
- import { createCell, formatGpuDuration, labelNode } from "./panelDomHelpers.js";
2
- import { createEmptyTableRow, createKindCell, createFilterSelect, createSearchInput, createSelectionCell, createTableScroller, createViewToolbar, groupPath, registerSelectable, updateSelectedRows, } from "./panelWorkbenchHelpers.js";
1
+ import { createCell, labelNode } from "./panelDomHelpers.js";
2
+ import { createEmptyTableRow, createKindCell, createFilterSelect, createSearchInput, createSelectionCell, createTableScroller, createViewToolbar, enableTabKeyboard, formatMeasuredGpuWork, formatTimingCoverage, groupPath, registerSelectable, selectionKey, updateSelectedRows, } from "./panelWorkbenchHelpers.js";
3
3
  export class PassesView {
4
4
  callbacks;
5
5
  root = document.createElement('section');
6
6
  toolbar = createViewToolbar('Pass filters and sorting');
7
+ groupToolbar = createViewToolbar('Group search');
7
8
  tabList = document.createElement('div');
8
9
  listButton = this.createSubviewButton('list', 'Pass List');
9
10
  groupsButton = this.createSubviewButton('groups', 'Group Hierarchy');
10
11
  listPane = document.createElement('div');
11
12
  groupsPane = document.createElement('div');
12
13
  listTable = createTableScroller([
13
- { label: 'Order', column: 'numeric' },
14
- { label: 'Segment', column: 'code' },
15
- { label: 'Label' },
16
- { label: 'Group' },
17
- { label: 'Kind', column: 'kind' },
18
- { label: 'GPU (ms)', column: 'numeric' },
19
- { label: 'Reads', column: 'numeric' },
20
- { label: 'Writes', column: 'numeric' },
14
+ { label: 'Name' }, { label: 'Compile state', column: 'kind' }, { label: 'Order', column: 'numeric' },
15
+ { label: 'Kind', column: 'kind' }, { label: 'CPU (ms)', column: 'numeric' }, { label: 'GPU (ms)', column: 'numeric' }, { label: 'R / W', column: 'numeric' },
21
16
  ]);
22
17
  groupsTable = createTableScroller([
23
- { label: '' },
24
- { label: 'Group' },
25
- { label: 'Retained', column: 'numeric' },
26
- { label: 'Culled', column: 'numeric' },
27
- { label: 'GPU work', column: 'numeric' },
28
- { label: 'Inputs', column: 'numeric' },
29
- { label: 'Outputs', column: 'numeric' },
18
+ { label: 'Group' }, { label: 'Retained', column: 'numeric' }, { label: 'Culled', column: 'numeric' },
19
+ { label: 'CPU sum / coverage', column: 'numeric' }, { label: 'GPU pass sum', column: 'numeric' }, { label: 'Inputs', column: 'numeric' },
20
+ { label: 'Outputs', column: 'numeric' }, { label: 'Locate' },
30
21
  ]);
31
22
  rows = new Map();
23
+ collapsedGroups = new Set();
24
+ count = document.createElement('span');
25
+ groupCount = document.createElement('span');
26
+ timing = document.createElement('p');
27
+ searchInput;
28
+ groupSearchInput;
29
+ kindSelect;
30
+ statusSelect;
32
31
  snapshot;
33
32
  selected;
34
33
  subview = 'list';
35
34
  search = '';
35
+ groupSearch = '';
36
36
  kind = 'all';
37
+ status = 'all';
37
38
  sort = 'order';
38
39
  constructor(callbacks, idPrefix) {
39
40
  this.callbacks = callbacks;
@@ -44,32 +45,44 @@ export class PassesView {
44
45
  this.tabList.setAttribute('role', 'tablist');
45
46
  this.tabList.setAttribute('aria-label', 'Pass views');
46
47
  this.tabList.append(this.listButton, this.groupsButton);
47
- const search = createSearchInput('Search pass or group', this.search, (value) => {
48
+ enableTabKeyboard(this.tabList);
49
+ this.searchInput = createSearchInput('Search pass, ID or group', '', (value) => {
48
50
  this.search = value.trim().toLocaleLowerCase();
49
51
  this.renderRows();
50
52
  });
51
- const kind = createFilterSelect('Pass kind', this.kind, [
52
- ['all', 'All kinds'],
53
- ['render', 'Render'],
54
- ['compute', 'Compute'],
55
- ['copy', 'Copy'],
56
- ['clear-buffer', 'Clear Buffer'],
57
- ['command', 'Command'],
58
- ['external-submission', 'External'],
59
- ], (value) => {
60
- this.kind = value;
53
+ this.statusSelect = createFilterSelect('Pass compile state', this.status, [
54
+ ['all', 'All'], ['retained', 'Retained'], ['culled', 'Culled'],
55
+ ], (value) => { this.status = value; this.renderRows(); });
56
+ this.kindSelect = createFilterSelect('Pass kind', this.kind, [
57
+ ['all', 'All kinds'], ['render', 'Render'], ['compute', 'Compute'], ['copy', 'Copy'],
58
+ ['clear-buffer', 'Clear Buffer'], ['command', 'Command'], ['external-submission', 'External'],
59
+ ], (value) => { this.kind = value; this.renderRows(); });
60
+ const sort = createFilterSelect('Sort passes', this.sort, [
61
+ ['order', 'Execution order'], ['label', 'Name'], ['kind', 'Kind'], ['gpu', 'GPU: slowest first'], ['cpu', 'CPU: slowest first'],
62
+ ], (value) => { this.sort = value; this.renderRows(); });
63
+ const clear = document.createElement('button');
64
+ clear.type = 'button';
65
+ clear.textContent = 'Clear filters';
66
+ clear.addEventListener('click', () => { this.clearFilters(); this.renderRows(); });
67
+ this.count.className = 'zenfg-inspector-result-count';
68
+ this.count.setAttribute('role', 'status');
69
+ this.toolbar.append(this.searchInput, this.statusSelect, this.kindSelect, sort, clear, this.count);
70
+ this.groupSearchInput = createSearchInput('Search group path or ID', '', (value) => {
71
+ this.groupSearch = value.trim().toLocaleLowerCase();
61
72
  this.renderRows();
62
73
  });
63
- const sort = createFilterSelect('Sort passes', this.sort, [
64
- ['order', 'Order'],
65
- ['label', 'Label'],
66
- ['kind', 'Kind'],
67
- ['gpu', 'GPU'],
68
- ], (value) => {
69
- this.sort = value;
74
+ const clearGroups = document.createElement('button');
75
+ clearGroups.type = 'button';
76
+ clearGroups.textContent = 'Clear filters';
77
+ clearGroups.addEventListener('click', () => {
78
+ this.groupSearch = '';
79
+ this.groupSearchInput.value = '';
70
80
  this.renderRows();
71
81
  });
72
- this.toolbar.append(search, kind, sort);
82
+ this.groupCount.className = 'zenfg-inspector-result-count';
83
+ this.groupCount.setAttribute('role', 'status');
84
+ this.groupToolbar.append(this.groupSearchInput, clearGroups, this.groupCount);
85
+ this.timing.className = 'zenfg-inspector-list-context';
73
86
  this.listButton.id = `${idPrefix}-list-subtab`;
74
87
  this.listButton.setAttribute('aria-controls', `${idPrefix}-pass-list-panel`);
75
88
  this.groupsButton.id = `${idPrefix}-groups-subtab`;
@@ -84,7 +97,7 @@ export class PassesView {
84
97
  this.groupsPane.setAttribute('role', 'tabpanel');
85
98
  this.groupsPane.setAttribute('aria-labelledby', this.groupsButton.id);
86
99
  this.groupsPane.appendChild(this.groupsTable.scroller);
87
- this.root.append(this.tabList, this.toolbar, this.listPane, this.groupsPane);
100
+ this.root.append(this.tabList, this.toolbar, this.groupToolbar, this.timing, this.listPane, this.groupsPane);
88
101
  this.updateSubview();
89
102
  }
90
103
  setSnapshot(snapshot) {
@@ -92,6 +105,9 @@ export class PassesView {
92
105
  if (snapshot.debugGroups.length === 0 && this.subview === 'groups')
93
106
  this.subview = 'list';
94
107
  this.groupsButton.disabled = snapshot.debugGroups.length === 0;
108
+ for (const path of this.collapsedGroups)
109
+ if (!snapshot.groupByPathKey.has(path))
110
+ this.collapsedGroups.delete(path);
95
111
  this.renderRows();
96
112
  this.updateSubview();
97
113
  }
@@ -99,25 +115,65 @@ export class PassesView {
99
115
  this.selected = selected;
100
116
  updateSelectedRows(this.rows, selected);
101
117
  }
118
+ showCulled() {
119
+ this.clearFilters();
120
+ this.status = 'culled';
121
+ this.statusSelect.value = 'culled';
122
+ this.subview = 'list';
123
+ this.updateSubview();
124
+ this.renderRows();
125
+ }
126
+ reveal(selection) {
127
+ if (selection.kind === 'group') {
128
+ this.subview = 'groups';
129
+ this.groupSearch = '';
130
+ this.groupSearchInput.value = '';
131
+ const group = this.snapshot?.groupByPathKey.get(selection.pathKey);
132
+ for (const id of group?.ancestorIds ?? []) {
133
+ const ancestor = this.snapshot?.groupById.get(id);
134
+ if (ancestor)
135
+ this.collapsedGroups.delete(ancestor.pathKey);
136
+ }
137
+ }
138
+ else if (selection.kind === 'node' || selection.kind === 'culled') {
139
+ this.subview = 'list';
140
+ this.clearFilters();
141
+ }
142
+ else
143
+ return;
144
+ this.updateSubview();
145
+ this.renderRows();
146
+ this.rows.get(selectionKey(selection))?.[0]?.scrollIntoView?.({ block: 'nearest' });
147
+ }
148
+ clearFilters() {
149
+ this.search = '';
150
+ this.kind = 'all';
151
+ this.status = 'all';
152
+ this.searchInput.value = '';
153
+ this.kindSelect.value = 'all';
154
+ this.statusSelect.value = 'all';
155
+ }
102
156
  createSubviewButton(subview, label) {
103
157
  const button = document.createElement('button');
104
158
  button.type = 'button';
105
159
  button.textContent = label;
106
160
  button.setAttribute('role', 'tab');
107
- button.addEventListener('click', () => {
108
- this.subview = subview;
109
- this.updateSubview();
110
- });
161
+ button.addEventListener('click', () => { this.subview = subview; this.updateSubview(); });
111
162
  return button;
112
163
  }
113
164
  updateSubview() {
114
165
  const listActive = this.subview === 'list';
115
- this.listButton.setAttribute('aria-selected', listActive ? 'true' : 'false');
116
- this.groupsButton.setAttribute('aria-selected', listActive ? 'false' : 'true');
166
+ this.listButton.setAttribute('aria-selected', String(listActive));
167
+ this.groupsButton.setAttribute('aria-selected', String(!listActive));
168
+ this.listButton.tabIndex = listActive ? 0 : -1;
169
+ this.groupsButton.tabIndex = listActive ? -1 : 0;
117
170
  this.listButton.classList.toggle('active', listActive);
118
171
  this.groupsButton.classList.toggle('active', !listActive);
119
172
  this.listPane.hidden = !listActive;
120
173
  this.groupsPane.hidden = listActive;
174
+ this.toolbar.hidden = !listActive;
175
+ this.groupToolbar.hidden = listActive;
176
+ this.timing.hidden = !listActive;
121
177
  }
122
178
  renderRows() {
123
179
  const snapshot = this.snapshot;
@@ -126,57 +182,131 @@ export class PassesView {
126
182
  this.rows.clear();
127
183
  this.listTable.body.replaceChildren();
128
184
  this.groupsTable.body.replaceChildren();
129
- const passes = snapshot.nodes.filter((node) => this.matchesNode(snapshot, node));
185
+ const entries = snapshot.protocol.graph.nodes.flatMap((canonical, index) => {
186
+ const node = snapshot.nodeById.get(canonical.id) ?? snapshot.culledById.get(canonical.id)?.node;
187
+ if (!node)
188
+ return [];
189
+ return [{ node,
190
+ selection: { kind: canonical.compileState.status === 'retained' ? 'node' : 'culled', id: node.id },
191
+ order: canonical.compileState.status === 'retained' ? canonical.compileState.executionOrder : undefined,
192
+ recordingOrder: canonical.recordingOrder ?? index,
193
+ }];
194
+ });
195
+ const passes = entries.filter((entry) => this.matchesNode(snapshot, entry));
130
196
  passes.sort((a, b) => this.compareNodes(a, b));
131
- for (const node of passes) {
132
- const selection = { kind: 'node', id: node.id };
197
+ this.count.textContent = `${passes.length} / ${entries.length} passes`;
198
+ const metrics = snapshot.metrics;
199
+ this.timing.textContent = `Retained means kept by compilation. CPU timing: ${formatTimingCoverage(metrics.cpuTimedNodeCount, snapshot.nodes.length)}. GPU timing: ${formatTimingCoverage(metrics.timedNodeCount, metrics.timingEligibleNodeCount)}${snapshot.profiling.status === 'unavailable' ? ` (${snapshot.profiling.reason})` : ''}.`;
200
+ for (const { node, selection, order } of passes) {
133
201
  const row = document.createElement('tr');
134
202
  registerSelectable(this.rows, row, selection, this.callbacks);
135
- const segment = snapshot.segmentByNodeId.get(node.id);
136
- row.append(createCell(String(node.order), { column: 'numeric' }), createCell(segment ? `${segment.index}:${segment.kind === 'frame-graph' ? 'FG' : 'opaque'}` : '-', { column: 'code' }), createSelectionCell(labelNode(node), selection, this.callbacks), createCell(groupPath(snapshot, node.debugGroupId), { column: 'code' }), createKindCell(node.kind), createCell(node.kind === 'external-submission' ? 'opaque' : formatGpuDuration(node), { column: 'numeric' }), createCell(String(node.reads.length), { column: 'numeric' }), createCell(String(node.writes.length), { column: 'numeric' }));
203
+ const labelCell = createSelectionCell(labelNode(node), selection, this.callbacks);
204
+ labelCell.title = node.id;
205
+ if (node.debugGroupId !== undefined) {
206
+ const group = document.createElement('small');
207
+ group.textContent = groupPath(snapshot, node.debugGroupId);
208
+ labelCell.appendChild(group);
209
+ }
210
+ const stateCell = createKindCell(selection.kind === 'culled' ? 'culled' : 'retained', selection.kind === 'culled' ? 'Culled' : 'Retained');
211
+ stateCell.title = selection.kind === 'culled' ? snapshot.culledById.get(node.id)?.reason ?? '' : 'Kept by compilation; this does not prove GPU execution.';
212
+ const gpu = selection.kind === 'culled' ? 'Not applicable' : node.kind === 'external-submission' ? 'Opaque'
213
+ : node.gpuDurationMicros !== undefined ? (node.gpuDurationMicros / 1000).toFixed(3)
214
+ : node.kind === 'render' || node.kind === 'compute' ? 'Not collected' : 'Not applicable';
215
+ const cpu = selection.kind === 'culled' ? 'Not executed' : node.cpuDurationMicros === undefined ? 'Not collected' : (node.cpuDurationMicros / 1000).toFixed(3);
216
+ const cpuCell = createCell(cpu, { column: 'numeric' });
217
+ cpuCell.title = 'Synchronous elapsed time; zero may reflect clock precision. External nodes include synchronous submission.';
218
+ row.append(labelCell, stateCell, createCell(order === undefined ? 'Not applicable' : String(order), { column: 'numeric' }), createKindCell(node.kind), cpuCell, createCell(gpu, { column: 'numeric' }), createCell(`${node.reads.length} / ${node.writes.length}`, { column: 'numeric' }));
137
219
  this.listTable.body.appendChild(row);
138
220
  }
139
221
  if (passes.length === 0)
140
- this.listTable.body.appendChild(createEmptyTableRow(8, 'No passes match the current filters.'));
141
- const query = this.search;
142
- for (const group of snapshot.debugGroups.filter((candidate) => (query.length === 0 || candidate.path.join(' / ').toLocaleLowerCase().includes(query)))) {
222
+ this.listTable.body.appendChild(createEmptyTableRow(7, 'No passes match the current filters.'));
223
+ this.renderGroups(snapshot);
224
+ updateSelectedRows(this.rows, this.selected);
225
+ }
226
+ renderGroups(snapshot) {
227
+ const included = new Set();
228
+ const childrenByParent = new Map();
229
+ for (const group of snapshot.debugGroups) {
230
+ const siblings = childrenByParent.get(group.parentId) ?? [];
231
+ siblings.push(group);
232
+ childrenByParent.set(group.parentId, siblings);
233
+ }
234
+ // Parent-before-child capture order need not be depth-first; keep each subtree together.
235
+ const orderedGroups = [];
236
+ const pending = [...(childrenByParent.get(undefined) ?? [])].reverse();
237
+ while (pending.length) {
238
+ const group = pending.pop();
239
+ orderedGroups.push(group);
240
+ pending.push(...[...(childrenByParent.get(group.id) ?? [])].reverse());
241
+ }
242
+ const parents = new Set(childrenByParent.keys());
243
+ if (this.groupSearch)
244
+ for (const group of snapshot.debugGroups) {
245
+ if (`${group.path.join(' / ')} ${group.id}`.toLocaleLowerCase().includes(this.groupSearch)) {
246
+ for (const id of group.ancestorIds)
247
+ included.add(id);
248
+ }
249
+ }
250
+ const groups = orderedGroups.filter((group) => this.groupSearch ? included.has(group.id)
251
+ : !group.ancestorIds.slice(0, -1).some((id) => this.collapsedGroups.has(snapshot.groupById.get(id).pathKey)));
252
+ this.groupCount.textContent = `${groups.length} / ${snapshot.debugGroups.length} groups`;
253
+ for (const group of groups) {
143
254
  const selection = { kind: 'group', pathKey: group.pathKey };
144
255
  const row = document.createElement('tr');
145
256
  registerSelectable(this.rows, row, selection, this.callbacks);
146
- const toggleCell = document.createElement('td');
257
+ const labelCell = createSelectionCell(group.label, selection, this.callbacks);
258
+ labelCell.style.paddingLeft = `${8 + group.depth * 18}px`;
259
+ labelCell.title = group.path.join(' / ');
147
260
  const toggle = document.createElement('button');
148
261
  toggle.type = 'button';
149
262
  toggle.className = 'zenfg-inspector-group-toggle';
150
- const expanded = this.callbacks.isGroupExpanded(group.pathKey);
151
- toggle.textContent = expanded ? '▾' : '▸';
152
- toggle.title = 'Toggle group in Graph view';
263
+ const expanded = this.groupSearch.length > 0 || !this.collapsedGroups.has(group.pathKey);
264
+ toggle.textContent = parents.has(group.id) ? expanded ? '▾' : '▸' : '·';
265
+ toggle.disabled = !parents.has(group.id) || this.groupSearch.length > 0;
266
+ toggle.title = this.groupSearch ? 'Matching groups and ancestors are expanded while searching.' : 'Toggle this group hierarchy';
153
267
  toggle.setAttribute('aria-label', `${expanded ? 'Collapse' : 'Expand'} group ${group.path.join(' / ')}`);
154
- toggle.addEventListener('click', () => this.callbacks.onGroupToggle(group.pathKey));
155
- toggleCell.appendChild(toggle);
156
- const labelCell = createSelectionCell(group.label, selection, this.callbacks);
157
- labelCell.style.paddingLeft = `${8 + group.depth * 18}px`;
268
+ if (parents.has(group.id))
269
+ toggle.setAttribute('aria-expanded', String(expanded));
270
+ toggle.addEventListener('click', () => {
271
+ if (expanded)
272
+ this.collapsedGroups.add(group.pathKey);
273
+ else
274
+ this.collapsedGroups.delete(group.pathKey);
275
+ this.renderRows();
276
+ this.rows.get(selectionKey(selection))?.[0]?.querySelector('.zenfg-inspector-group-toggle')?.focus({ preventScroll: true });
277
+ });
278
+ labelCell.prepend(toggle);
158
279
  const summary = group.summary;
159
- row.append(toggleCell, labelCell, createCell(String(summary.retainedNodeCount), { column: 'numeric' }), createCell(String(summary.culledNodeCount), { column: 'numeric' }), createCell(summary.timedNodeCount === 0 ? '-' : (summary.gpuWorkDurationMicros / 1000).toFixed(3), { column: 'numeric' }), createCell(String(summary.inputResources.length), { column: 'numeric' }), createCell(String(summary.outputResources.length), { column: 'numeric' }));
280
+ const revealCell = document.createElement('td');
281
+ const reveal = document.createElement('button');
282
+ reveal.type = 'button';
283
+ reveal.className = 'zenfg-inspector-relation-button';
284
+ reveal.textContent = 'Show in Graph';
285
+ reveal.addEventListener('click', () => this.callbacks.onReveal?.(selection, 'graph'));
286
+ revealCell.appendChild(reveal);
287
+ row.append(labelCell, createCell(String(summary.retainedNodeCount), { column: 'numeric' }), createCell(String(summary.culledNodeCount), { column: 'numeric' }), createCell((summary.cpuTimedNodeCount ? (summary.cpuWorkDurationMicros / 1000).toFixed(3) + ' ms' : 'Not collected') + ' · ' + formatTimingCoverage(summary.cpuTimedNodeCount, summary.retainedNodeCount), { column: 'numeric' }), createCell(formatMeasuredGpuWork(summary.gpuWorkDurationMicros, summary.timedNodeCount, summary.timingEligibleNodeCount), { column: 'numeric' }), createCell(String(summary.inputResources.length), { column: 'numeric' }), createCell(String(summary.outputResources.length), { column: 'numeric' }), revealCell);
160
288
  this.groupsTable.body.appendChild(row);
161
289
  }
162
- if (this.groupsTable.body.childElementCount === 0)
163
- this.groupsTable.body.appendChild(createEmptyTableRow(7, 'No diagnostic groups.'));
164
- updateSelectedRows(this.rows, this.selected);
290
+ if (groups.length === 0)
291
+ this.groupsTable.body.appendChild(createEmptyTableRow(8, 'No groups match the current filters.'));
165
292
  }
166
- matchesNode(snapshot, node) {
293
+ matchesNode(snapshot, entry) {
294
+ const { node, selection } = entry;
295
+ if (this.status === 'retained' && selection.kind !== 'node' || this.status === 'culled' && selection.kind !== 'culled')
296
+ return false;
167
297
  if (this.kind !== 'all' && node.kind !== this.kind)
168
298
  return false;
169
- if (this.search.length === 0)
170
- return true;
171
- const haystack = `${labelNode(node)} ${groupPath(snapshot, node.debugGroupId)}`.toLocaleLowerCase();
172
- return haystack.includes(this.search);
299
+ return !this.search || `${labelNode(node)} ${node.id} ${groupPath(snapshot, node.debugGroupId)}`.toLocaleLowerCase().includes(this.search);
173
300
  }
174
301
  compareNodes(a, b) {
302
+ const order = () => a.order === undefined ? b.order === undefined ? a.recordingOrder - b.recordingOrder : 1
303
+ : b.order === undefined ? -1 : a.order - b.order;
175
304
  switch (this.sort) {
176
- case 'label': return labelNode(a).localeCompare(labelNode(b)) || a.order - b.order;
177
- case 'kind': return a.kind.localeCompare(b.kind) || a.order - b.order;
178
- case 'gpu': return (b.gpuDurationMicros ?? -1) - (a.gpuDurationMicros ?? -1) || a.order - b.order;
179
- case 'order': return a.order - b.order;
305
+ case 'label': return labelNode(a.node).localeCompare(labelNode(b.node)) || order();
306
+ case 'kind': return a.node.kind.localeCompare(b.node.kind) || order();
307
+ case 'cpu': return (b.node.cpuDurationMicros ?? -1) - (a.node.cpuDurationMicros ?? -1) || order();
308
+ case 'gpu': return (b.node.gpuDurationMicros ?? -1) - (a.node.gpuDurationMicros ?? -1) || order();
309
+ case 'order': return order();
180
310
  }
181
311
  }
182
312
  }
@@ -1 +1 @@
1
- {"version":3,"file":"panelPassesView.js","sourceRoot":"","sources":["../src/panelPassesView.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FrameGraphDebugNode, FrameGraphDebugViewModel } from './debugCaptureModel.ts';\nimport { createCell, formatGpuDuration, labelNode } from './panelDomHelpers.ts';\nimport type { PassesSubview, Selection } from './panelTypes.ts';\nimport {\n\tcreateEmptyTableRow,\n\tcreateKindCell,\n\tcreateFilterSelect,\n\tcreateSearchInput,\n\tcreateSelectionCell,\n\tcreateTableScroller,\n\tcreateViewToolbar,\n\tgroupPath,\n\tregisterSelectable,\n\ttype WorkbenchCallbacks,\n\tupdateSelectedRows,\n} from './panelWorkbenchHelpers.ts';\n\ntype PassSort = 'order' | 'label' | 'kind' | 'gpu';\n\nexport class PassesView {\n\treadonly root = document.createElement('section');\n\tprivate readonly toolbar = createViewToolbar('Pass filters and sorting');\n\tprivate readonly tabList = document.createElement('div');\n\tprivate readonly listButton = this.createSubviewButton('list', 'Pass List');\n\tprivate readonly groupsButton = this.createSubviewButton('groups', 'Group Hierarchy');\n\tprivate readonly listPane = document.createElement('div');\n\tprivate readonly groupsPane = document.createElement('div');\n\tprivate readonly listTable = createTableScroller([\n\t\t{ label: 'Order', column: 'numeric' },\n\t\t{ label: 'Segment', column: 'code' },\n\t\t{ label: 'Label' },\n\t\t{ label: 'Group' },\n\t\t{ label: 'Kind', column: 'kind' },\n\t\t{ label: 'GPU (ms)', column: 'numeric' },\n\t\t{ label: 'Reads', column: 'numeric' },\n\t\t{ label: 'Writes', column: 'numeric' },\n\t]);\n\tprivate readonly groupsTable = createTableScroller([\n\t\t{ label: '' },\n\t\t{ label: 'Group' },\n\t\t{ label: 'Retained', column: 'numeric' },\n\t\t{ label: 'Culled', column: 'numeric' },\n\t\t{ label: 'GPU work', column: 'numeric' },\n\t\t{ label: 'Inputs', column: 'numeric' },\n\t\t{ label: 'Outputs', column: 'numeric' },\n\t]);\n\tprivate readonly rows = new Map<string, HTMLElement[]>();\n\tprivate snapshot: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\tprivate subview: PassesSubview = 'list';\n\tprivate search = '';\n\tprivate kind = 'all';\n\tprivate sort: PassSort = 'order';\n\n\tconstructor(private readonly callbacks: WorkbenchCallbacks, idPrefix: string) {\n\t\tthis.root.className = 'zenfg-inspector-view zenfg-inspector-passes-view';\n\t\tthis.root.id = `${idPrefix}-view-passes`;\n\t\tthis.root.setAttribute('role', 'tabpanel');\n\t\tthis.tabList.className = 'zenfg-inspector-subtabs';\n\t\tthis.tabList.setAttribute('role', 'tablist');\n\t\tthis.tabList.setAttribute('aria-label', 'Pass views');\n\t\tthis.tabList.append(this.listButton, this.groupsButton);\n\n\t\tconst search = createSearchInput('Search pass or group', this.search, (value) => {\n\t\t\tthis.search = value.trim().toLocaleLowerCase();\n\t\t\tthis.renderRows();\n\t\t});\n\t\tconst kind = createFilterSelect('Pass kind', this.kind, [\n\t\t\t['all', 'All kinds'],\n\t\t\t['render', 'Render'],\n\t\t\t['compute', 'Compute'],\n\t\t\t['copy', 'Copy'],\n\t\t\t['clear-buffer', 'Clear Buffer'],\n\t\t\t['command', 'Command'],\n\t\t\t['external-submission', 'External'],\n\t\t], (value) => {\n\t\t\tthis.kind = value;\n\t\t\tthis.renderRows();\n\t\t});\n\t\tconst sort = createFilterSelect('Sort passes', this.sort, [\n\t\t\t['order', 'Order'],\n\t\t\t['label', 'Label'],\n\t\t\t['kind', 'Kind'],\n\t\t\t['gpu', 'GPU'],\n\t\t], (value) => {\n\t\t\tthis.sort = value as PassSort;\n\t\t\tthis.renderRows();\n\t\t});\n\t\tthis.toolbar.append(search, kind, sort);\n\n\t\tthis.listButton.id = `${idPrefix}-list-subtab`;\n\t\tthis.listButton.setAttribute('aria-controls', `${idPrefix}-pass-list-panel`);\n\t\tthis.groupsButton.id = `${idPrefix}-groups-subtab`;\n\t\tthis.groupsButton.setAttribute('aria-controls', `${idPrefix}-group-list-panel`);\n\t\tthis.listPane.id = `${idPrefix}-pass-list-panel`;\n\t\tthis.listPane.className = 'zenfg-inspector-subview';\n\t\tthis.listPane.setAttribute('role', 'tabpanel');\n\t\tthis.listPane.setAttribute('aria-labelledby', this.listButton.id);\n\t\tthis.listPane.appendChild(this.listTable.scroller);\n\t\tthis.groupsPane.id = `${idPrefix}-group-list-panel`;\n\t\tthis.groupsPane.className = 'zenfg-inspector-subview';\n\t\tthis.groupsPane.setAttribute('role', 'tabpanel');\n\t\tthis.groupsPane.setAttribute('aria-labelledby', this.groupsButton.id);\n\t\tthis.groupsPane.appendChild(this.groupsTable.scroller);\n\t\tthis.root.append(this.tabList, this.toolbar, this.listPane, this.groupsPane);\n\t\tthis.updateSubview();\n\t}\n\n\tsetSnapshot(snapshot: FrameGraphDebugViewModel): void {\n\t\tthis.snapshot = snapshot;\n\t\tif (snapshot.debugGroups.length === 0 && this.subview === 'groups') this.subview = 'list';\n\t\tthis.groupsButton.disabled = snapshot.debugGroups.length === 0;\n\t\tthis.renderRows();\n\t\tthis.updateSubview();\n\t}\n\n\tsetSelection(selected: Selection | undefined): void {\n\t\tthis.selected = selected;\n\t\tupdateSelectedRows(this.rows, selected);\n\t}\n\n\tprivate createSubviewButton(subview: PassesSubview, label: string): HTMLButtonElement {\n\t\tconst button = document.createElement('button');\n\t\tbutton.type = 'button';\n\t\tbutton.textContent = label;\n\t\tbutton.setAttribute('role', 'tab');\n\t\tbutton.addEventListener('click', () => {\n\t\t\tthis.subview = subview;\n\t\t\tthis.updateSubview();\n\t\t});\n\t\treturn button;\n\t}\n\n\tprivate updateSubview(): void {\n\t\tconst listActive = this.subview === 'list';\n\t\tthis.listButton.setAttribute('aria-selected', listActive ? 'true' : 'false');\n\t\tthis.groupsButton.setAttribute('aria-selected', listActive ? 'false' : 'true');\n\t\tthis.listButton.classList.toggle('active', listActive);\n\t\tthis.groupsButton.classList.toggle('active', !listActive);\n\t\tthis.listPane.hidden = !listActive;\n\t\tthis.groupsPane.hidden = listActive;\n\t}\n\n\tprivate renderRows(): void {\n\t\tconst snapshot = this.snapshot;\n\t\tif (!snapshot) return;\n\t\tthis.rows.clear();\n\t\tthis.listTable.body.replaceChildren();\n\t\tthis.groupsTable.body.replaceChildren();\n\n\t\tconst passes = snapshot.nodes.filter((node) => this.matchesNode(snapshot, node));\n\t\tpasses.sort((a, b) => this.compareNodes(a, b));\n\t\tfor (const node of passes) {\n\t\t\tconst selection: Selection = { kind: 'node', id: node.id };\n\t\t\tconst row = document.createElement('tr');\n\t\t\tregisterSelectable(this.rows, row, selection, this.callbacks);\n\t\t\tconst segment = snapshot.segmentByNodeId.get(node.id);\n\t\t\trow.append(\n\t\t\t\tcreateCell(String(node.order), { column: 'numeric' }),\n\t\t\t\tcreateCell(segment ? `${segment.index}:${segment.kind === 'frame-graph' ? 'FG' : 'opaque'}` : '-', { column: 'code' }),\n\t\t\t\tcreateSelectionCell(labelNode(node), selection, this.callbacks),\n\t\t\t\tcreateCell(groupPath(snapshot, node.debugGroupId), { column: 'code' }),\n\t\t\t\tcreateKindCell(node.kind),\n\t\t\t\tcreateCell(node.kind === 'external-submission' ? 'opaque' : formatGpuDuration(node), { column: 'numeric' }),\n\t\t\t\tcreateCell(String(node.reads.length), { column: 'numeric' }),\n\t\t\t\tcreateCell(String(node.writes.length), { column: 'numeric' }),\n\t\t\t);\n\t\t\tthis.listTable.body.appendChild(row);\n\t\t}\n\t\tif (passes.length === 0) this.listTable.body.appendChild(createEmptyTableRow(8, 'No passes match the current filters.'));\n\n\t\tconst query = this.search;\n\t\tfor (const group of snapshot.debugGroups.filter((candidate) => (\n\t\t\tquery.length === 0 || candidate.path.join(' / ').toLocaleLowerCase().includes(query)\n\t\t))) {\n\t\t\tconst selection: Selection = { kind: 'group', pathKey: group.pathKey };\n\t\t\tconst row = document.createElement('tr');\n\t\t\tregisterSelectable(this.rows, row, selection, this.callbacks);\n\t\t\tconst toggleCell = document.createElement('td');\n\t\t\tconst toggle = document.createElement('button');\n\t\t\ttoggle.type = 'button';\n\t\t\ttoggle.className = 'zenfg-inspector-group-toggle';\n\t\t\tconst expanded = this.callbacks.isGroupExpanded(group.pathKey);\n\t\t\ttoggle.textContent = expanded ? '▾' : '▸';\n\t\t\ttoggle.title = 'Toggle group in Graph view';\n\t\t\ttoggle.setAttribute('aria-label', `${expanded ? 'Collapse' : 'Expand'} group ${group.path.join(' / ')}`);\n\t\t\ttoggle.addEventListener('click', () => this.callbacks.onGroupToggle(group.pathKey));\n\t\t\ttoggleCell.appendChild(toggle);\n\t\t\tconst labelCell = createSelectionCell(group.label, selection, this.callbacks);\n\t\t\tlabelCell.style.paddingLeft = `${8 + group.depth * 18}px`;\n\t\t\tconst summary = group.summary;\n\t\t\trow.append(\n\t\t\t\ttoggleCell,\n\t\t\t\tlabelCell,\n\t\t\t\tcreateCell(String(summary.retainedNodeCount), { column: 'numeric' }),\n\t\t\t\tcreateCell(String(summary.culledNodeCount), { column: 'numeric' }),\n\t\t\t\tcreateCell(summary.timedNodeCount === 0 ? '-' : (summary.gpuWorkDurationMicros / 1000).toFixed(3), { column: 'numeric' }),\n\t\t\t\tcreateCell(String(summary.inputResources.length), { column: 'numeric' }),\n\t\t\t\tcreateCell(String(summary.outputResources.length), { column: 'numeric' }),\r\n\t\t\t);\n\t\t\tthis.groupsTable.body.appendChild(row);\n\t\t}\n\t\tif (this.groupsTable.body.childElementCount === 0) this.groupsTable.body.appendChild(createEmptyTableRow(7, 'No diagnostic groups.'));\n\t\tupdateSelectedRows(this.rows, this.selected);\n\t}\n\n\tprivate matchesNode(snapshot: FrameGraphDebugViewModel, node: FrameGraphDebugNode): boolean {\n\t\tif (this.kind !== 'all' && node.kind !== this.kind) return false;\n\t\tif (this.search.length === 0) return true;\n\t\tconst haystack = `${labelNode(node)} ${groupPath(snapshot, node.debugGroupId)}`.toLocaleLowerCase();\n\t\treturn haystack.includes(this.search);\n\t}\n\n\tprivate compareNodes(a: FrameGraphDebugNode, b: FrameGraphDebugNode): number {\n\t\tswitch (this.sort) {\n\t\t\tcase 'label': return labelNode(a).localeCompare(labelNode(b)) || a.order - b.order;\n\t\t\tcase 'kind': return a.kind.localeCompare(b.kind) || a.order - b.order;\n\t\t\tcase 'gpu': return (b.gpuDurationMicros ?? -1) - (a.gpuDurationMicros ?? -1) || a.order - b.order;\n\t\t\tcase 'order': return a.order - b.order;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"panelPassesView.js","sourceRoot":"","sources":["../src/panelPassesView.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FrameGraphDebugGroup, FrameGraphDebugNode, FrameGraphDebugViewModel } from './debugCaptureModel.ts';\nimport { createCell, labelNode } from './panelDomHelpers.ts';\nimport type { PassesSubview, Selection } from './panelTypes.ts';\nimport {\n\tcreateEmptyTableRow, createKindCell, createFilterSelect, createSearchInput, createSelectionCell,\n\tcreateTableScroller, createViewToolbar, enableTabKeyboard, formatMeasuredGpuWork, formatTimingCoverage,\n\tgroupPath, registerSelectable, selectionKey, type WorkbenchCallbacks, updateSelectedRows,\n} from './panelWorkbenchHelpers.ts';\n\ntype PassSort = 'order' | 'label' | 'kind' | 'gpu' | 'cpu';\ntype PassEntry = {\n\treadonly node: Omit<FrameGraphDebugNode, 'order'>;\n\treadonly selection: Selection;\n\treadonly order?: number;\n\treadonly recordingOrder: number;\n};\n\nexport class PassesView {\n\treadonly root = document.createElement('section');\n\tprivate readonly toolbar = createViewToolbar('Pass filters and sorting');\n\tprivate readonly groupToolbar = createViewToolbar('Group search');\n\tprivate readonly tabList = document.createElement('div');\n\tprivate readonly listButton = this.createSubviewButton('list', 'Pass List');\n\tprivate readonly groupsButton = this.createSubviewButton('groups', 'Group Hierarchy');\n\tprivate readonly listPane = document.createElement('div');\n\tprivate readonly groupsPane = document.createElement('div');\n\tprivate readonly listTable = createTableScroller([\n\t\t{ label: 'Name' }, { label: 'Compile state', column: 'kind' }, { label: 'Order', column: 'numeric' },\n\t\t{ label: 'Kind', column: 'kind' }, { label: 'CPU (ms)', column: 'numeric' }, { label: 'GPU (ms)', column: 'numeric' }, { label: 'R / W', column: 'numeric' },\n\t]);\n\tprivate readonly groupsTable = createTableScroller([\n\t\t{ label: 'Group' }, { label: 'Retained', column: 'numeric' }, { label: 'Culled', column: 'numeric' },\n\t\t{ label: 'CPU sum / coverage', column: 'numeric' }, { label: 'GPU pass sum', column: 'numeric' }, { label: 'Inputs', column: 'numeric' },\n\t\t{ label: 'Outputs', column: 'numeric' }, { label: 'Locate' },\n\t]);\n\tprivate readonly rows = new Map<string, HTMLElement[]>();\n\tprivate readonly collapsedGroups = new Set<string>();\n\tprivate readonly count = document.createElement('span');\n\tprivate readonly groupCount = document.createElement('span');\n\tprivate readonly timing = document.createElement('p');\n\tprivate readonly searchInput: HTMLInputElement;\n\tprivate readonly groupSearchInput: HTMLInputElement;\n\tprivate readonly kindSelect: HTMLSelectElement;\n\tprivate readonly statusSelect: HTMLSelectElement;\n\tprivate snapshot: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\tprivate subview: PassesSubview = 'list';\n\tprivate search = '';\n\tprivate groupSearch = '';\n\tprivate kind = 'all';\n\tprivate status = 'all';\n\tprivate sort: PassSort = 'order';\n\n\tconstructor(private readonly callbacks: WorkbenchCallbacks, idPrefix: string) {\n\t\tthis.root.className = 'zenfg-inspector-view zenfg-inspector-passes-view';\n\t\tthis.root.id = `${idPrefix}-view-passes`;\n\t\tthis.root.setAttribute('role', 'tabpanel');\n\t\tthis.tabList.className = 'zenfg-inspector-subtabs';\n\t\tthis.tabList.setAttribute('role', 'tablist');\n\t\tthis.tabList.setAttribute('aria-label', 'Pass views');\n\t\tthis.tabList.append(this.listButton, this.groupsButton);\n\t\tenableTabKeyboard(this.tabList);\n\t\tthis.searchInput = createSearchInput('Search pass, ID or group', '', (value) => {\n\t\t\tthis.search = value.trim().toLocaleLowerCase(); this.renderRows();\n\t\t});\n\t\tthis.statusSelect = createFilterSelect('Pass compile state', this.status, [\n\t\t\t['all', 'All'], ['retained', 'Retained'], ['culled', 'Culled'],\n\t\t], (value) => { this.status = value; this.renderRows(); });\n\t\tthis.kindSelect = createFilterSelect('Pass kind', this.kind, [\n\t\t\t['all', 'All kinds'], ['render', 'Render'], ['compute', 'Compute'], ['copy', 'Copy'],\n\t\t\t['clear-buffer', 'Clear Buffer'], ['command', 'Command'], ['external-submission', 'External'],\n\t\t], (value) => { this.kind = value; this.renderRows(); });\n\t\tconst sort = createFilterSelect('Sort passes', this.sort, [\n\t\t\t['order', 'Execution order'], ['label', 'Name'], ['kind', 'Kind'], ['gpu', 'GPU: slowest first'], ['cpu', 'CPU: slowest first'],\n\t\t], (value) => { this.sort = value as PassSort; this.renderRows(); });\n\t\tconst clear = document.createElement('button');\n\t\tclear.type = 'button'; clear.textContent = 'Clear filters';\n\t\tclear.addEventListener('click', () => { this.clearFilters(); this.renderRows(); });\n\t\tthis.count.className = 'zenfg-inspector-result-count'; this.count.setAttribute('role', 'status');\n\t\tthis.toolbar.append(this.searchInput, this.statusSelect, this.kindSelect, sort, clear, this.count);\n\t\tthis.groupSearchInput = createSearchInput('Search group path or ID', '', (value) => {\n\t\t\tthis.groupSearch = value.trim().toLocaleLowerCase(); this.renderRows();\n\t\t});\n\t\tconst clearGroups = document.createElement('button');\n\t\tclearGroups.type = 'button'; clearGroups.textContent = 'Clear filters';\n\t\tclearGroups.addEventListener('click', () => {\n\t\t\tthis.groupSearch = ''; this.groupSearchInput.value = ''; this.renderRows();\n\t\t});\n\t\tthis.groupCount.className = 'zenfg-inspector-result-count'; this.groupCount.setAttribute('role', 'status');\n\t\tthis.groupToolbar.append(this.groupSearchInput, clearGroups, this.groupCount);\n\t\tthis.timing.className = 'zenfg-inspector-list-context';\n\t\tthis.listButton.id = `${idPrefix}-list-subtab`;\n\t\tthis.listButton.setAttribute('aria-controls', `${idPrefix}-pass-list-panel`);\n\t\tthis.groupsButton.id = `${idPrefix}-groups-subtab`;\n\t\tthis.groupsButton.setAttribute('aria-controls', `${idPrefix}-group-list-panel`);\n\t\tthis.listPane.id = `${idPrefix}-pass-list-panel`; this.listPane.className = 'zenfg-inspector-subview';\n\t\tthis.listPane.setAttribute('role', 'tabpanel'); this.listPane.setAttribute('aria-labelledby', this.listButton.id);\n\t\tthis.listPane.appendChild(this.listTable.scroller);\n\t\tthis.groupsPane.id = `${idPrefix}-group-list-panel`; this.groupsPane.className = 'zenfg-inspector-subview';\n\t\tthis.groupsPane.setAttribute('role', 'tabpanel'); this.groupsPane.setAttribute('aria-labelledby', this.groupsButton.id);\n\t\tthis.groupsPane.appendChild(this.groupsTable.scroller);\n\t\tthis.root.append(this.tabList, this.toolbar, this.groupToolbar, this.timing, this.listPane, this.groupsPane);\n\t\tthis.updateSubview();\n\t}\n\n\tsetSnapshot(snapshot: FrameGraphDebugViewModel): void {\n\t\tthis.snapshot = snapshot;\n\t\tif (snapshot.debugGroups.length === 0 && this.subview === 'groups') this.subview = 'list';\n\t\tthis.groupsButton.disabled = snapshot.debugGroups.length === 0;\n\t\tfor (const path of this.collapsedGroups) if (!snapshot.groupByPathKey.has(path)) this.collapsedGroups.delete(path);\n\t\tthis.renderRows(); this.updateSubview();\n\t}\n\n\tsetSelection(selected: Selection | undefined): void {\n\t\tthis.selected = selected; updateSelectedRows(this.rows, selected);\n\t}\n\n\tshowCulled(): void {\n\t\tthis.clearFilters(); this.status = 'culled'; this.statusSelect.value = 'culled'; this.subview = 'list';\n\t\tthis.updateSubview(); this.renderRows();\n\t}\n\n\treveal(selection: Selection): void {\n\t\tif (selection.kind === 'group') {\n\t\t\tthis.subview = 'groups'; this.groupSearch = ''; this.groupSearchInput.value = '';\n\t\t\tconst group = this.snapshot?.groupByPathKey.get(selection.pathKey);\n\t\t\tfor (const id of group?.ancestorIds ?? []) {\n\t\t\t\tconst ancestor = this.snapshot?.groupById.get(id);\n\t\t\t\tif (ancestor) this.collapsedGroups.delete(ancestor.pathKey);\n\t\t\t}\n\t\t} else if (selection.kind === 'node' || selection.kind === 'culled') {\n\t\t\tthis.subview = 'list'; this.clearFilters();\n\t\t} else return;\n\t\tthis.updateSubview(); this.renderRows();\n\t\tthis.rows.get(selectionKey(selection))?.[0]?.scrollIntoView?.({ block: 'nearest' });\n\t}\n\n\tprivate clearFilters(): void {\n\t\tthis.search = ''; this.kind = 'all'; this.status = 'all';\n\t\tthis.searchInput.value = ''; this.kindSelect.value = 'all'; this.statusSelect.value = 'all';\n\t}\n\n\tprivate createSubviewButton(subview: PassesSubview, label: string): HTMLButtonElement {\n\t\tconst button = document.createElement('button'); button.type = 'button'; button.textContent = label;\n\t\tbutton.setAttribute('role', 'tab');\n\t\tbutton.addEventListener('click', () => { this.subview = subview; this.updateSubview(); });\n\t\treturn button;\n\t}\n\n\tprivate updateSubview(): void {\n\t\tconst listActive = this.subview === 'list';\n\t\tthis.listButton.setAttribute('aria-selected', String(listActive));\n\t\tthis.groupsButton.setAttribute('aria-selected', String(!listActive));\n\t\tthis.listButton.tabIndex = listActive ? 0 : -1; this.groupsButton.tabIndex = listActive ? -1 : 0;\n\t\tthis.listButton.classList.toggle('active', listActive); this.groupsButton.classList.toggle('active', !listActive);\n\t\tthis.listPane.hidden = !listActive; this.groupsPane.hidden = listActive;\n\t\tthis.toolbar.hidden = !listActive; this.groupToolbar.hidden = listActive; this.timing.hidden = !listActive;\n\t}\n\n\tprivate renderRows(): void {\n\t\tconst snapshot = this.snapshot;\n\t\tif (!snapshot) return;\n\t\tthis.rows.clear(); this.listTable.body.replaceChildren(); this.groupsTable.body.replaceChildren();\n\t\tconst entries = snapshot.protocol.graph.nodes.flatMap((canonical, index): PassEntry[] => {\n\t\t\tconst node = snapshot.nodeById.get(canonical.id) ?? snapshot.culledById.get(canonical.id)?.node;\n\t\t\tif (!node) return [];\n\t\t\treturn [{ node,\n\t\t\t\tselection: { kind: canonical.compileState.status === 'retained' ? 'node' : 'culled', id: node.id },\n\t\t\t\torder: canonical.compileState.status === 'retained' ? canonical.compileState.executionOrder : undefined,\n\t\t\t\trecordingOrder: canonical.recordingOrder ?? index,\n\t\t\t}];\n\t\t});\n\t\tconst passes = entries.filter((entry) => this.matchesNode(snapshot, entry));\n\t\tpasses.sort((a, b) => this.compareNodes(a, b)); this.count.textContent = `${passes.length} / ${entries.length} passes`;\n\t\tconst metrics = snapshot.metrics;\n\t\tthis.timing.textContent = `Retained means kept by compilation. CPU timing: ${formatTimingCoverage(metrics.cpuTimedNodeCount, snapshot.nodes.length)}. GPU timing: ${formatTimingCoverage(metrics.timedNodeCount, metrics.timingEligibleNodeCount)}${snapshot.profiling.status === 'unavailable' ? ` (${snapshot.profiling.reason})` : ''}.`;\n\t\tfor (const { node, selection, order } of passes) {\n\t\t\tconst row = document.createElement('tr'); registerSelectable(this.rows, row, selection, this.callbacks);\n\t\t\tconst labelCell = createSelectionCell(labelNode(node), selection, this.callbacks); labelCell.title = node.id;\n\t\t\tif (node.debugGroupId !== undefined) {\n\t\t\t\tconst group = document.createElement('small'); group.textContent = groupPath(snapshot, node.debugGroupId); labelCell.appendChild(group);\n\t\t\t}\n\t\t\tconst stateCell = createKindCell(selection.kind === 'culled' ? 'culled' : 'retained', selection.kind === 'culled' ? 'Culled' : 'Retained');\n\t\t\tstateCell.title = selection.kind === 'culled' ? snapshot.culledById.get(node.id)?.reason ?? '' : 'Kept by compilation; this does not prove GPU execution.';\n\t\t\tconst gpu = selection.kind === 'culled' ? 'Not applicable' : node.kind === 'external-submission' ? 'Opaque'\n\t\t\t\t: node.gpuDurationMicros !== undefined ? (node.gpuDurationMicros / 1000).toFixed(3)\n\t\t\t\t\t: node.kind === 'render' || node.kind === 'compute' ? 'Not collected' : 'Not applicable';\n\t\t\tconst cpu = selection.kind === 'culled' ? 'Not executed' : node.cpuDurationMicros === undefined ? 'Not collected' : (node.cpuDurationMicros / 1000).toFixed(3);\n\t\t\tconst cpuCell = createCell(cpu, { column: 'numeric' });\n\t\t\tcpuCell.title = 'Synchronous elapsed time; zero may reflect clock precision. External nodes include synchronous submission.';\n\t\t\trow.append(labelCell, stateCell, createCell(order === undefined ? 'Not applicable' : String(order), { column: 'numeric' }),\n\t\t\t\tcreateKindCell(node.kind), cpuCell, createCell(gpu, { column: 'numeric' }), createCell(`${node.reads.length} / ${node.writes.length}`, { column: 'numeric' }));\n\t\t\tthis.listTable.body.appendChild(row);\n\t\t}\n\t\tif (passes.length === 0) this.listTable.body.appendChild(createEmptyTableRow(7, 'No passes match the current filters.'));\n\t\tthis.renderGroups(snapshot); updateSelectedRows(this.rows, this.selected);\n\t}\n\n\tprivate renderGroups(snapshot: FrameGraphDebugViewModel): void {\n\t\tconst included = new Set<string>();\n\t\tconst childrenByParent = new Map<string | undefined, FrameGraphDebugGroup[]>();\n\t\tfor (const group of snapshot.debugGroups) {\n\t\t\tconst siblings = childrenByParent.get(group.parentId) ?? [];\n\t\t\tsiblings.push(group);\n\t\t\tchildrenByParent.set(group.parentId, siblings);\n\t\t}\n\t\t// Parent-before-child capture order need not be depth-first; keep each subtree together.\n\t\tconst orderedGroups: FrameGraphDebugGroup[] = [];\n\t\tconst pending = [...(childrenByParent.get(undefined) ?? [])].reverse();\n\t\twhile (pending.length) {\n\t\t\tconst group = pending.pop()!;\n\t\t\torderedGroups.push(group);\n\t\t\tpending.push(...[...(childrenByParent.get(group.id) ?? [])].reverse());\n\t\t}\n\t\tconst parents = new Set(childrenByParent.keys());\n\t\tif (this.groupSearch) for (const group of snapshot.debugGroups) {\n\t\t\tif (`${group.path.join(' / ')} ${group.id}`.toLocaleLowerCase().includes(this.groupSearch)) {\n\t\t\t\tfor (const id of group.ancestorIds) included.add(id);\n\t\t\t}\n\t\t}\n\t\tconst groups = orderedGroups.filter((group) => this.groupSearch ? included.has(group.id)\n\t\t\t: !group.ancestorIds.slice(0, -1).some((id) => this.collapsedGroups.has(snapshot.groupById.get(id)!.pathKey)));\n\t\tthis.groupCount.textContent = `${groups.length} / ${snapshot.debugGroups.length} groups`;\n\t\tfor (const group of groups) {\n\t\t\tconst selection: Selection = { kind: 'group', pathKey: group.pathKey };\n\t\t\tconst row = document.createElement('tr'); registerSelectable(this.rows, row, selection, this.callbacks);\n\t\t\tconst labelCell = createSelectionCell(group.label, selection, this.callbacks);\n\t\t\tlabelCell.style.paddingLeft = `${8 + group.depth * 18}px`; labelCell.title = group.path.join(' / ');\n\t\t\tconst toggle = document.createElement('button'); toggle.type = 'button'; toggle.className = 'zenfg-inspector-group-toggle';\n\t\t\tconst expanded = this.groupSearch.length > 0 || !this.collapsedGroups.has(group.pathKey);\n\t\t\ttoggle.textContent = parents.has(group.id) ? expanded ? '▾' : '▸' : '·';\n\t\t\ttoggle.disabled = !parents.has(group.id) || this.groupSearch.length > 0;\n\t\t\ttoggle.title = this.groupSearch ? 'Matching groups and ancestors are expanded while searching.' : 'Toggle this group hierarchy';\n\t\t\ttoggle.setAttribute('aria-label', `${expanded ? 'Collapse' : 'Expand'} group ${group.path.join(' / ')}`);\n\t\t\tif (parents.has(group.id)) toggle.setAttribute('aria-expanded', String(expanded));\n\t\t\ttoggle.addEventListener('click', () => {\n\t\t\t\tif (expanded) this.collapsedGroups.add(group.pathKey); else this.collapsedGroups.delete(group.pathKey);\n\t\t\t\tthis.renderRows();\n\t\t\t\tthis.rows.get(selectionKey(selection))?.[0]?.querySelector<HTMLButtonElement>('.zenfg-inspector-group-toggle')?.focus({ preventScroll: true });\n\t\t\t});\n\t\t\tlabelCell.prepend(toggle);\n\t\t\tconst summary = group.summary;\n\t\t\tconst revealCell = document.createElement('td'); const reveal = document.createElement('button');\n\t\t\treveal.type = 'button'; reveal.className = 'zenfg-inspector-relation-button'; reveal.textContent = 'Show in Graph';\n\t\t\treveal.addEventListener('click', () => this.callbacks.onReveal?.(selection, 'graph')); revealCell.appendChild(reveal);\n\t\t\trow.append(labelCell, createCell(String(summary.retainedNodeCount), { column: 'numeric' }),\n\t\t\t\tcreateCell(String(summary.culledNodeCount), { column: 'numeric' }),\n\t\t\t\tcreateCell((summary.cpuTimedNodeCount ? (summary.cpuWorkDurationMicros / 1000).toFixed(3) + ' ms' : 'Not collected') + ' · ' + formatTimingCoverage(summary.cpuTimedNodeCount, summary.retainedNodeCount), { column: 'numeric' }),\n\t\t\t\tcreateCell(formatMeasuredGpuWork(summary.gpuWorkDurationMicros, summary.timedNodeCount, summary.timingEligibleNodeCount), { column: 'numeric' }),\n\t\t\t\tcreateCell(String(summary.inputResources.length), { column: 'numeric' }),\n\t\t\t\tcreateCell(String(summary.outputResources.length), { column: 'numeric' }), revealCell);\n\t\t\tthis.groupsTable.body.appendChild(row);\n\t\t}\n\t\tif (groups.length === 0) this.groupsTable.body.appendChild(createEmptyTableRow(8, 'No groups match the current filters.'));\n\t}\n\n\tprivate matchesNode(snapshot: FrameGraphDebugViewModel, entry: PassEntry): boolean {\n\t\tconst { node, selection } = entry;\n\t\tif (this.status === 'retained' && selection.kind !== 'node' || this.status === 'culled' && selection.kind !== 'culled') return false;\n\t\tif (this.kind !== 'all' && node.kind !== this.kind) return false;\n\t\treturn !this.search || `${labelNode(node)} ${node.id} ${groupPath(snapshot, node.debugGroupId)}`.toLocaleLowerCase().includes(this.search);\n\t}\n\n\tprivate compareNodes(a: PassEntry, b: PassEntry): number {\n\t\tconst order = () => a.order === undefined ? b.order === undefined ? a.recordingOrder - b.recordingOrder : 1\n\t\t\t: b.order === undefined ? -1 : a.order - b.order;\n\t\tswitch (this.sort) {\n\t\t\tcase 'label': return labelNode(a.node).localeCompare(labelNode(b.node)) || order();\n\t\t\tcase 'kind': return a.node.kind.localeCompare(b.node.kind) || order();\n\t\t\tcase 'cpu': return (b.node.cpuDurationMicros ?? -1) - (a.node.cpuDurationMicros ?? -1) || order();\n\t\t\tcase 'gpu': return (b.node.gpuDurationMicros ?? -1) - (a.node.gpuDurationMicros ?? -1) || order();\n\t\t\tcase 'order': return order();\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import type { SelectedCanonicalDetail } from './panelSelection.ts';
2
+ /** Created only when Raw is visited and retained for the current object/capture. */
3
+ export declare class RawDetailView {
4
+ private readonly detail;
5
+ readonly root: HTMLDivElement;
6
+ private readonly tree;
7
+ private readonly status;
8
+ private readonly expanded;
9
+ private query;
10
+ private readonly json;
11
+ constructor(detail: SelectedCanonicalDetail, migrated: boolean);
12
+ private renderTree;
13
+ private createValue;
14
+ }
15
+ //# sourceMappingURL=panelRawView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panelRawView.d.ts","sourceRoot":"","sources":["../src/panelRawView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAGnE,oFAAoF;AACpF,qBAAa,aAAa;IAQb,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPnC,QAAQ,CAAC,IAAI,iBAAiC;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;IACnD,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAED,MAAM,EAAE,uBAAuB,EAAE,QAAQ,EAAE,OAAO;IA+C/E,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,WAAW;CAgCnB"}