@forgeax/engine-rhi-debug 0.1.34 → 0.1.35

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.
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/replay/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/replay/session.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/engine-rhi-debug",
3
- "version": "0.1.34",
3
+ "version": "0.1.35",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -26,19 +26,19 @@
26
26
  "LICENSE"
27
27
  ],
28
28
  "dependencies": {
29
- "@forgeax/engine-rhi": "0.1.34",
30
- "@forgeax/engine-types": "0.1.34",
29
+ "@forgeax/engine-rhi": "0.1.35",
30
+ "@forgeax/engine-types": "0.1.35",
31
31
  "@noble/hashes": "^2.2.0",
32
32
  "pako": "^1.0.11"
33
33
  },
34
34
  "devDependencies": {
35
- "@forgeax/engine-rhi-null": "0.1.34",
35
+ "@forgeax/engine-rhi-null": "0.1.35",
36
36
  "@types/node": "^20.14.0",
37
37
  "@webgpu/types": "^0.1.71"
38
38
  },
39
39
  "peerDependencies": {
40
- "@forgeax/engine-rhi-webgpu": "0.1.34",
41
- "@forgeax/engine-rhi-wgpu": "0.1.34"
40
+ "@forgeax/engine-rhi-webgpu": "0.1.35",
41
+ "@forgeax/engine-rhi-wgpu": "0.1.35"
42
42
  },
43
43
  "forgeax": {
44
44
  "metrics": {
@@ -142,6 +142,7 @@ async function captureBrowserTape(): Promise<CapturedBrowserTape> {
142
142
  'write source texture',
143
143
  );
144
144
  const encoder = must(device.createCommandEncoder({}), 'create command encoder');
145
+ encoder.pushDebugGroup('frame');
145
146
  const pass = encoder.beginRenderPass({
146
147
  colorAttachments: [
147
148
  {
@@ -154,8 +155,13 @@ async function captureBrowserTape(): Promise<CapturedBrowserTape> {
154
155
  } as never);
155
156
  pass.setPipeline(pipeline);
156
157
  pass.setBindGroup(0, bindGroup, []);
158
+ pass.pushDebugGroup('outer');
159
+ pass.pushDebugGroup('inner');
157
160
  pass.draw(3, 1, 0, 0);
161
+ pass.popDebugGroup();
162
+ pass.popDebugGroup();
158
163
  pass.end();
164
+ encoder.popDebugGroup();
159
165
  const command = must(encoder.finish(), 'finish command encoder');
160
166
  must(device.queue.submit([command]), 'submit command buffer');
161
167
  await device.queue.onSubmittedWorkDone();
@@ -103,6 +103,7 @@ async function makeRecording(pack: DawnPack): Promise<{
103
103
  const encoderResult = device.createCommandEncoder({});
104
104
  expect(encoderResult.ok).toBe(true);
105
105
  if (!encoderResult.ok) throw new Error(encoderResult.error.hint);
106
+ encoderResult.value.pushDebugGroup('frame');
106
107
  const pass = encoderResult.value.beginRenderPass({
107
108
  colorAttachments: [
108
109
  {
@@ -114,8 +115,13 @@ async function makeRecording(pack: DawnPack): Promise<{
114
115
  ],
115
116
  } as never);
116
117
  pass.setPipeline(pipeline.value);
118
+ pass.pushDebugGroup('outer');
119
+ pass.pushDebugGroup('inner');
117
120
  pass.draw(3, 1, 0, 0);
121
+ pass.popDebugGroup();
122
+ pass.popDebugGroup();
118
123
  pass.end();
124
+ encoderResult.value.popDebugGroup();
119
125
  const command = encoderResult.value.finish();
120
126
  expect(command.ok).toBe(true);
121
127
  if (!command.ok) throw new Error(command.error.hint);
@@ -127,7 +133,7 @@ async function makeRecording(pack: DawnPack): Promise<{
127
133
  }
128
134
 
129
135
  describe.skipIf(SKIP_DAWN)('RHI debug v7 fresh-device evidence', () => {
130
- it('records, encodes, strictly decodes, and replays pixels on a fresh Dawn device', async () => {
136
+ it('records, encodes, strictly decodes, and replays pixels through nested debug groups on a fresh Dawn device', async () => {
131
137
  const pack = await loadDawn();
132
138
  const recording = await makeRecording(pack);
133
139
  const baseline = await readbackTexturePixels(
@@ -594,6 +594,13 @@ async function finalizeWorkPass(
594
594
  finishEventIndex ?? context.tape.events.length,
595
595
  );
596
596
  if (!closure.ok) return closure;
597
+ const groupsClosed = closeReplayDebugGroups(
598
+ context,
599
+ begin.cmdHandleId,
600
+ work.eventIndex,
601
+ encoder.resource.value as RhiCommandEncoder,
602
+ );
603
+ if (!groupsClosed.ok) return groupsClosed;
597
604
  const finished = (encoder.resource.value as RhiCommandEncoder).finish();
598
605
  const finishEvent = context.tape.events[finishEventIndex ?? work.eventIndex] ?? begin;
599
606
  if (!finished.ok)
@@ -656,6 +663,15 @@ function closeReplayPass(
656
663
  );
657
664
  }
658
665
  }
666
+ if (entry.resource.role === 'render-pass') {
667
+ const groupsClosed = closeReplayDebugGroups(
668
+ context,
669
+ begin.passHandleId,
670
+ selectedEventIndex,
671
+ entry.resource.value as RhiRenderPassEncoder,
672
+ );
673
+ if (!groupsClosed.ok) return groupsClosed;
674
+ }
659
675
  (entry.resource.value as RhiRenderPassEncoder | RhiComputePassEncoder).end();
660
676
  } catch (cause) {
661
677
  return eventFailure(pass.endEventIndex ?? selectedEventIndex, begin, 'encode', cause);
@@ -664,6 +680,42 @@ function closeReplayPass(
664
680
  return ok(undefined);
665
681
  }
666
682
 
683
+ // Inspection stops at the selected work, before the recorded scope exits.
684
+ // Derive only the still-open scopes from that prefix; never execute later work.
685
+ function closeReplayDebugGroups(
686
+ context: ReplayExecutionContext,
687
+ handleId: string,
688
+ throughEventIndex: number,
689
+ encoder: RhiCommandEncoder | RhiRenderPassEncoder,
690
+ ): Result<void, RhiDebugError> {
691
+ const open: { event: RhiCallEvent; eventIndex: number }[] = [];
692
+ for (let eventIndex = 0; eventIndex <= throughEventIndex; eventIndex++) {
693
+ const event = context.tape.events[eventIndex];
694
+ if (event === undefined) continue;
695
+ if (
696
+ (event.kind === 'pushDebugGroup' && event.cmdHandleId === handleId) ||
697
+ (event.kind === 'passPushDebugGroup' && event.passHandleId === handleId)
698
+ ) {
699
+ open.push({ event, eventIndex });
700
+ } else if (
701
+ (event.kind === 'popDebugGroup' && event.cmdHandleId === handleId) ||
702
+ (event.kind === 'passPopDebugGroup' && event.passHandleId === handleId)
703
+ ) {
704
+ open.pop();
705
+ }
706
+ }
707
+ for (let index = open.length - 1; index >= 0; index--) {
708
+ const scope = open[index];
709
+ if (scope === undefined) continue;
710
+ try {
711
+ encoder.popDebugGroup();
712
+ } catch (cause) {
713
+ return eventFailure(scope.eventIndex, scope.event, 'encode', cause);
714
+ }
715
+ }
716
+ return ok(undefined);
717
+ }
718
+
667
719
  async function replayCommandClosure(
668
720
  context: ReplayExecutionContext,
669
721
  cmdHandleId: string,