@forgeax/engine-app 0.1.7 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/browser-frame-signal.browser.test.d.ts +2 -0
- package/dist/__tests__/browser-frame-signal.browser.test.d.ts.map +1 -0
- package/dist/__tests__/browser-frame-signal.unit.test.d.ts +2 -0
- package/dist/__tests__/browser-frame-signal.unit.test.d.ts.map +1 -0
- package/dist/__tests__/tool-preview-runtime-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/tool-preview-runtime-contract.unit.test.d.ts.map +1 -0
- package/dist/canvas-policy.d.ts.map +1 -1
- package/dist/create-app.d.ts.map +1 -1
- package/dist/engine-worker-runtime.mjs +1 -0
- package/dist/engine-worker-runtime.mjs.map +1 -1
- package/dist/index.mjs +75 -28
- package/dist/index.mjs.map +1 -1
- package/dist/internal/browser-rhi-debug-runtime.d.ts +2 -2
- package/dist/internal/browser-rhi-debug-runtime.d.ts.map +1 -1
- package/dist/tool-preview/bootstrap.d.ts.map +1 -1
- package/package.json +25 -25
- package/src/__tests__/browser-frame-signal.browser.test.ts +20 -0
- package/src/__tests__/browser-frame-signal.unit.test.ts +35 -0
- package/src/__tests__/create-app-stop.test.ts +10 -6
- package/src/__tests__/create-app.test.ts +13 -1
- package/src/__tests__/tool-preview-runtime-contract.unit.test.ts +47 -0
- package/src/browser-frame-signal.ts +4 -4
- package/src/canvas-policy.ts +1 -0
- package/src/create-app.ts +1 -0
- package/src/internal/browser-rhi-debug-runtime.ts +9 -6
- package/src/tool-preview/bootstrap.ts +55 -13
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Renderer } from '@forgeax/engine-render';
|
|
2
2
|
import type { RhiDevice, RhiInstance } from '@forgeax/engine-rhi';
|
|
3
|
-
import type { CreateShaderModuleFn, RecorderAttachment } from '@forgeax/engine-rhi-debug';
|
|
3
|
+
import type { CreateShaderModuleFn, RecorderAttachment, V7Tape } from '@forgeax/engine-rhi-debug';
|
|
4
4
|
export interface BrowserRhiDebugRuntime {
|
|
5
5
|
readonly rhi: RhiInstance;
|
|
6
6
|
readonly attachment: RecorderAttachment;
|
|
7
|
-
readonly createReplayDevice: () => Promise<import('@forgeax/engine-types').Result<RhiDevice, unknown>>;
|
|
7
|
+
readonly createReplayDevice: (tape: V7Tape) => Promise<import('@forgeax/engine-types').Result<RhiDevice, unknown>>;
|
|
8
8
|
readonly createShaderModule: CreateShaderModuleFn;
|
|
9
9
|
readonly rhiInstrumentation: import('@forgeax/engine-render/internal/construct-renderer').RhiBackendInstrumentation;
|
|
10
10
|
attachRenderer(renderer: Renderer): () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-rhi-debug-runtime.d.ts","sourceRoot":"","sources":["../../src/internal/browser-rhi-debug-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EACV,oBAAoB,EAEpB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"browser-rhi-debug-runtime.d.ts","sourceRoot":"","sources":["../../src/internal/browser-rhi-debug-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EACV,oBAAoB,EAEpB,kBAAkB,EAClB,MAAM,EACP,MAAM,2BAA2B,CAAC;AAInC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,kBAAkB,EAAE,CAC3B,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,OAAO,uBAAuB,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IACzE,QAAQ,CAAC,kBAAkB,EAAE,oBAAoB,CAAC;IAClD,QAAQ,CAAC,kBAAkB,EAAE,OAAO,oDAAoD,EAAE,yBAAyB,CAAC;IACpH,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,IAAI,CAAC;CAChD;AAmBD;;;;GAIG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAyBpF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/tool-preview/bootstrap.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/tool-preview/bootstrap.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/engine-app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -23,32 +23,32 @@
|
|
|
23
23
|
"LICENSE"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@forgeax/engine-animation": "0.1.
|
|
27
|
-
"@forgeax/engine-assets-runtime": "0.1.
|
|
28
|
-
"@forgeax/engine-audio": "0.1.
|
|
29
|
-
"@forgeax/engine-audio-webaudio": "0.1.
|
|
30
|
-
"@forgeax/engine-debug-draw": "0.1.
|
|
31
|
-
"@forgeax/engine-ecs": "0.1.
|
|
32
|
-
"@forgeax/engine-input": "0.1.
|
|
33
|
-
"@forgeax/engine-physics": "0.1.
|
|
34
|
-
"@forgeax/engine-physics-rapier2d": "0.1.
|
|
35
|
-
"@forgeax/engine-physics-rapier3d": "0.1.
|
|
36
|
-
"@forgeax/engine-plugin": "0.1.
|
|
37
|
-
"@forgeax/engine-profiler": "0.1.
|
|
38
|
-
"@forgeax/engine-render": "0.1.
|
|
39
|
-
"@forgeax/engine-rhi": "0.1.
|
|
40
|
-
"@forgeax/engine-
|
|
41
|
-
"@forgeax/engine-
|
|
42
|
-
"@forgeax/engine-
|
|
43
|
-
"@forgeax/engine-
|
|
44
|
-
"@forgeax/engine-
|
|
26
|
+
"@forgeax/engine-animation": "0.1.20",
|
|
27
|
+
"@forgeax/engine-assets-runtime": "0.1.20",
|
|
28
|
+
"@forgeax/engine-audio": "0.1.20",
|
|
29
|
+
"@forgeax/engine-audio-webaudio": "0.1.20",
|
|
30
|
+
"@forgeax/engine-debug-draw": "0.1.20",
|
|
31
|
+
"@forgeax/engine-ecs": "0.1.20",
|
|
32
|
+
"@forgeax/engine-input": "0.1.20",
|
|
33
|
+
"@forgeax/engine-physics": "0.1.20",
|
|
34
|
+
"@forgeax/engine-physics-rapier2d": "0.1.20",
|
|
35
|
+
"@forgeax/engine-physics-rapier3d": "0.1.20",
|
|
36
|
+
"@forgeax/engine-plugin": "0.1.20",
|
|
37
|
+
"@forgeax/engine-profiler": "0.1.20",
|
|
38
|
+
"@forgeax/engine-render": "0.1.20",
|
|
39
|
+
"@forgeax/engine-rhi": "0.1.20",
|
|
40
|
+
"@forgeax/engine-rhi-debug": "0.1.20",
|
|
41
|
+
"@forgeax/engine-runtime": "0.1.20",
|
|
42
|
+
"@forgeax/engine-scene": "0.1.20",
|
|
43
|
+
"@forgeax/engine-state": "0.1.20",
|
|
44
|
+
"@forgeax/engine-tool-runtime": "0.1.20",
|
|
45
|
+
"@forgeax/engine-types": "0.1.20"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@forgeax/engine-remote": "0.1.
|
|
48
|
-
"@forgeax/engine-rhi-
|
|
49
|
-
"@forgeax/engine-rhi-
|
|
50
|
-
"@forgeax/engine-rhi-
|
|
51
|
-
"@forgeax/engine-rhi-wgpu": "0.1.7",
|
|
48
|
+
"@forgeax/engine-remote": "0.1.20",
|
|
49
|
+
"@forgeax/engine-rhi-null": "0.1.20",
|
|
50
|
+
"@forgeax/engine-rhi-webgpu": "0.1.20",
|
|
51
|
+
"@forgeax/engine-rhi-wgpu": "0.1.20",
|
|
52
52
|
"@types/ws": "^8.5.10",
|
|
53
53
|
"@webgpu/types": "^0.1.71",
|
|
54
54
|
"ws": "^8.20.0"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
FORGEAX_FRAME_SUBMITTED_EVENT,
|
|
5
|
+
publishBrowserFrameSubmitted,
|
|
6
|
+
} from '../browser-frame-signal';
|
|
7
|
+
|
|
8
|
+
describe('publishBrowserFrameSubmitted in a browser', () => {
|
|
9
|
+
it('dispatches frame-submitted on a real HTMLCanvasElement', () => {
|
|
10
|
+
const canvas = document.createElement('canvas');
|
|
11
|
+
const received: Event[] = [];
|
|
12
|
+
canvas.addEventListener(FORGEAX_FRAME_SUBMITTED_EVENT, (event) => received.push(event));
|
|
13
|
+
|
|
14
|
+
publishBrowserFrameSubmitted(canvas, { frameId: 11, deviceGeneration: 4 });
|
|
15
|
+
|
|
16
|
+
expect(received).toHaveLength(1);
|
|
17
|
+
expect(received[0]).toBeInstanceOf(CustomEvent);
|
|
18
|
+
expect((received[0] as CustomEvent).detail).toEqual({ frameId: 11, deviceGeneration: 4 });
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
FORGEAX_FRAME_SUBMITTED_EVENT,
|
|
5
|
+
publishBrowserFrameSubmitted,
|
|
6
|
+
} from '../browser-frame-signal';
|
|
7
|
+
|
|
8
|
+
describe('publishBrowserFrameSubmitted', () => {
|
|
9
|
+
it('projects Dawn canvas progress without requiring DOM event methods', () => {
|
|
10
|
+
const documentElement = { dataset: {} as DOMStringMap };
|
|
11
|
+
const canvas = { ownerDocument: { documentElement } } as HTMLCanvasElement;
|
|
12
|
+
|
|
13
|
+
expect(() =>
|
|
14
|
+
publishBrowserFrameSubmitted(canvas, { frameId: 7, deviceGeneration: 2 }),
|
|
15
|
+
).not.toThrow();
|
|
16
|
+
expect(documentElement.dataset.forgeaxFrameSubmitted).toBe('7');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('dispatches the browser event when the canvas supports dispatchEvent', () => {
|
|
20
|
+
let dispatchedEvent: Event | undefined;
|
|
21
|
+
const dispatchEvent = (event: Event): boolean => {
|
|
22
|
+
dispatchedEvent = event;
|
|
23
|
+
return true;
|
|
24
|
+
};
|
|
25
|
+
const canvas = { dispatchEvent } as unknown as HTMLCanvasElement;
|
|
26
|
+
|
|
27
|
+
publishBrowserFrameSubmitted(canvas, { frameId: 9, deviceGeneration: 3 });
|
|
28
|
+
|
|
29
|
+
expect(dispatchedEvent).toBeInstanceOf(CustomEvent);
|
|
30
|
+
if (!(dispatchedEvent instanceof CustomEvent))
|
|
31
|
+
throw new Error('frame event was not dispatched');
|
|
32
|
+
expect(dispatchedEvent.type).toBe(FORGEAX_FRAME_SUBMITTED_EVENT);
|
|
33
|
+
expect(dispatchedEvent.detail).toEqual({ frameId: 9, deviceGeneration: 3 });
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -392,8 +392,9 @@ describe('feat-20260619 M3: auto-register audioTickSystem', () => {
|
|
|
392
392
|
addEventListener: vi.fn(),
|
|
393
393
|
removeEventListener: vi.fn(),
|
|
394
394
|
});
|
|
395
|
-
|
|
396
|
-
|
|
395
|
+
globalThis.AudioContext = vi.fn(function AudioContextMock() {
|
|
396
|
+
return makeMockAudioContextForApp();
|
|
397
|
+
}) as unknown as typeof AudioContext;
|
|
397
398
|
|
|
398
399
|
const rafStub = installRafStub();
|
|
399
400
|
|
|
@@ -458,6 +459,7 @@ describe('feat-20260619 M3: auto-register audioTickSystem', () => {
|
|
|
458
459
|
expect(rafStub.tickFn).not.toBeNull();
|
|
459
460
|
rafStub.tickFn?.();
|
|
460
461
|
|
|
462
|
+
expect(world.execution.health).toBe('healthy');
|
|
461
463
|
expect(playSpy).toHaveBeenCalledTimes(1);
|
|
462
464
|
|
|
463
465
|
app.stop();
|
|
@@ -477,8 +479,9 @@ describe('feat-20260619 M3: auto-register audioTickSystem', () => {
|
|
|
477
479
|
addEventListener: vi.fn(),
|
|
478
480
|
removeEventListener: vi.fn(),
|
|
479
481
|
});
|
|
480
|
-
|
|
481
|
-
|
|
482
|
+
globalThis.AudioContext = vi.fn(function AudioContextMock() {
|
|
483
|
+
return makeMockAudioContextForApp();
|
|
484
|
+
}) as unknown as typeof AudioContext;
|
|
482
485
|
|
|
483
486
|
const rafStub = installRafStub();
|
|
484
487
|
|
|
@@ -543,8 +546,9 @@ describe('feat-20260619 M3: auto-register audioTickSystem', () => {
|
|
|
543
546
|
addEventListener: vi.fn(),
|
|
544
547
|
removeEventListener: vi.fn(),
|
|
545
548
|
});
|
|
546
|
-
|
|
547
|
-
|
|
549
|
+
globalThis.AudioContext = vi.fn(function AudioContextMock() {
|
|
550
|
+
return makeMockAudioContextForApp();
|
|
551
|
+
}) as unknown as typeof AudioContext;
|
|
548
552
|
|
|
549
553
|
const rafStub = installRafStub();
|
|
550
554
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import { World } from '@forgeax/engine-ecs';
|
|
25
25
|
import { Camera, orthographic, perspective } from '@forgeax/engine-render';
|
|
26
|
-
import { describe, expect, it } from 'vitest';
|
|
26
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
27
27
|
|
|
28
28
|
import { syncCameraAspect, syncCanvasDrawingBuffer } from '../create-app';
|
|
29
29
|
import { resolveRhiDebugFlag } from '../internal/rhi-debug-flag';
|
|
@@ -231,6 +231,18 @@ describe('create-app.test.ts', () => {
|
|
|
231
231
|
expect(r.value.aspect).toBeCloseTo(2, 5);
|
|
232
232
|
});
|
|
233
233
|
|
|
234
|
+
it('does not journal a same-f32 aspect on every frame', () => {
|
|
235
|
+
const world = new World();
|
|
236
|
+
world.spawn({ component: Camera, data: perspective({ fov: 1, aspect: 1 }) }).unwrap();
|
|
237
|
+
const set = vi.spyOn(world, 'set');
|
|
238
|
+
|
|
239
|
+
syncCameraAspect(world, 1280, 720);
|
|
240
|
+
syncCameraAspect(world, 1280, 720);
|
|
241
|
+
|
|
242
|
+
expect(set).toHaveBeenCalledTimes(1);
|
|
243
|
+
set.mockRestore();
|
|
244
|
+
});
|
|
245
|
+
|
|
234
246
|
it('autoAspect=false camera is left untouched', () => {
|
|
235
247
|
const world = new World();
|
|
236
248
|
const cam = world
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
|
|
4
|
+
const bootstrapSource = readFileSync(
|
|
5
|
+
new URL('../tool-preview/bootstrap.ts', import.meta.url),
|
|
6
|
+
'utf8',
|
|
7
|
+
);
|
|
8
|
+
const runtimeSource = readFileSync(
|
|
9
|
+
new URL('../internal/browser-rhi-debug-runtime.ts', import.meta.url),
|
|
10
|
+
'utf8',
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
describe('tool preview runtime contract', () => {
|
|
14
|
+
it('captures one rendered frame after warmup and the live-resource snapshot', () => {
|
|
15
|
+
const finalFrame = bootstrapSource.indexOf('if (frame === recipe.frames - 1)');
|
|
16
|
+
const armed = bootstrapSource.indexOf(
|
|
17
|
+
'encodedCapture = runtime.attachment.captureFrame()',
|
|
18
|
+
finalFrame,
|
|
19
|
+
);
|
|
20
|
+
const snapshot = bootstrapSource.indexOf('runtime.attachment.frameBoundary()', armed);
|
|
21
|
+
const rendered = bootstrapSource.indexOf('app.stepFrame(recipe.deltaSeconds)', snapshot);
|
|
22
|
+
const finalized = bootstrapSource.indexOf(
|
|
23
|
+
'const finalized = await runtime.attachment.frameBoundary()',
|
|
24
|
+
rendered,
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
expect(finalFrame).toBeGreaterThan(-1);
|
|
28
|
+
expect(armed).toBeGreaterThan(finalFrame);
|
|
29
|
+
expect(snapshot).toBeGreaterThan(armed);
|
|
30
|
+
expect(rendered).toBeGreaterThan(snapshot);
|
|
31
|
+
expect(finalized).toBeGreaterThan(rendered);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('requests replay features and limits from the recorded tape', () => {
|
|
35
|
+
expect(bootstrapSource).toContain('runtime.createReplayDevice(parsed.value)');
|
|
36
|
+
expect(runtimeSource).toContain('createReplayDevice: async (tape)');
|
|
37
|
+
expect(runtimeSource).toContain(
|
|
38
|
+
'replayDeviceRequest(tape, adapter.value.features, adapter.value.limits)',
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('publishes owner identity only after the recorded tape proves a subject draw', () => {
|
|
43
|
+
expect(bootstrapSource).toContain("resource.kind === 'material' || resource.kind === 'mesh'");
|
|
44
|
+
expect(bootstrapSource).toContain('return drawCalls > 2');
|
|
45
|
+
expect(bootstrapSource).toContain('observation: capture.resource.ownerFacts');
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -30,10 +30,10 @@ export function publishBrowserFrameSubmitted(
|
|
|
30
30
|
if (documentElement !== undefined) {
|
|
31
31
|
documentElement.dataset[FORGEAX_FRAME_SUBMITTED_DATASET] = String(event.frameId);
|
|
32
32
|
}
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
33
|
+
// Dawn-node smoke canvases intentionally expose only the drawing-buffer
|
|
34
|
+
// surface; they are not DOM EventTargets. Keep the document projection
|
|
35
|
+
// above useful for those hosts, while dispatching the browser event only
|
|
36
|
+
// when the host actually provides the optional EventTarget capability.
|
|
37
37
|
if (typeof CustomEvent === 'function' && typeof canvas.dispatchEvent === 'function') {
|
|
38
38
|
canvas.dispatchEvent(
|
|
39
39
|
new CustomEvent(FORGEAX_FRAME_SUBMITTED_EVENT, {
|
package/src/canvas-policy.ts
CHANGED
|
@@ -11,6 +11,7 @@ export function syncCameraAspect(world: World, canvasW: number, canvasH: number)
|
|
|
11
11
|
if (!camera.ok) continue;
|
|
12
12
|
if (camera.value.autoAspect !== true) continue;
|
|
13
13
|
if (camera.value.projection !== CAMERA_PROJECTION_PERSPECTIVE) continue;
|
|
14
|
+
if (camera.value.aspect === Math.fround(aspect)) continue;
|
|
14
15
|
world.set(row.entity, Camera, { aspect });
|
|
15
16
|
}
|
|
16
17
|
}
|
package/src/create-app.ts
CHANGED
|
@@ -808,6 +808,7 @@ export function syncCameraAspect(world: World, canvasW: number, canvasH: number)
|
|
|
808
808
|
// perspective discriminator is the numeric column value.
|
|
809
809
|
if (r.value.autoAspect !== true) continue;
|
|
810
810
|
if (r.value.projection !== CAMERA_PROJECTION_PERSPECTIVE) continue;
|
|
811
|
+
if (r.value.aspect === Math.fround(aspect)) continue;
|
|
811
812
|
world.set(entity, Camera, { aspect });
|
|
812
813
|
}
|
|
813
814
|
}
|
|
@@ -4,16 +4,17 @@ import type {
|
|
|
4
4
|
CreateShaderModuleFn,
|
|
5
5
|
RecordableBackend,
|
|
6
6
|
RecorderAttachment,
|
|
7
|
+
V7Tape,
|
|
7
8
|
} from '@forgeax/engine-rhi-debug';
|
|
8
|
-
import { attachRecorder } from '@forgeax/engine-rhi-debug';
|
|
9
|
+
import { attachRecorder, replayDeviceRequest } from '@forgeax/engine-rhi-debug';
|
|
9
10
|
import { createRhiInstrumentation } from './rhi-capture';
|
|
10
11
|
|
|
11
12
|
export interface BrowserRhiDebugRuntime {
|
|
12
13
|
readonly rhi: RhiInstance;
|
|
13
14
|
readonly attachment: RecorderAttachment;
|
|
14
|
-
readonly createReplayDevice: (
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
readonly createReplayDevice: (
|
|
16
|
+
tape: V7Tape,
|
|
17
|
+
) => Promise<import('@forgeax/engine-types').Result<RhiDevice, unknown>>;
|
|
17
18
|
readonly createShaderModule: CreateShaderModuleFn;
|
|
18
19
|
readonly rhiInstrumentation: import('@forgeax/engine-render/internal/construct-renderer').RhiBackendInstrumentation;
|
|
19
20
|
attachRenderer(renderer: Renderer): () => void;
|
|
@@ -51,10 +52,12 @@ export async function createBrowserRhiDebugRuntime(): Promise<BrowserRhiDebugRun
|
|
|
51
52
|
attachment,
|
|
52
53
|
createShaderModule: backend.createShaderModule,
|
|
53
54
|
rhiInstrumentation: createRhiInstrumentation(attachment),
|
|
54
|
-
createReplayDevice: async () => {
|
|
55
|
+
createReplayDevice: async (tape) => {
|
|
55
56
|
const adapter = await backend.rhi.requestAdapter();
|
|
56
57
|
if (!adapter.ok) return adapter;
|
|
57
|
-
return adapter.value.requestDevice(
|
|
58
|
+
return adapter.value.requestDevice(
|
|
59
|
+
replayDeviceRequest(tape, adapter.value.features, adapter.value.limits),
|
|
60
|
+
);
|
|
58
61
|
},
|
|
59
62
|
attachRenderer(_renderer: Renderer): () => void {
|
|
60
63
|
// Frame boundaries and device loss are connected by the typed
|
|
@@ -203,6 +203,12 @@ function resourceSubjectDigest(resource: ToolPreviewResourceFacts | undefined):
|
|
|
203
203
|
return candidates.find((value): value is string => typeof value === 'string' && value.length > 0);
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
function resourceSubjectDrawn(resource: ToolPreviewResourceFacts, drawCalls: number): boolean {
|
|
207
|
+
if (resource.kind === 'texture') return drawCalls > 0;
|
|
208
|
+
if (resource.kind === 'material' || resource.kind === 'mesh') return drawCalls > 2;
|
|
209
|
+
return resource.observation !== undefined;
|
|
210
|
+
}
|
|
211
|
+
|
|
206
212
|
export async function replayToolPreviewCapture(
|
|
207
213
|
capture: ToolPreviewCaptureResult,
|
|
208
214
|
): Promise<Result<ToolPreviewRunResult, ToolPreviewHostError>> {
|
|
@@ -217,13 +223,29 @@ export async function replayToolPreviewCapture(
|
|
|
217
223
|
detail: { phase: 'tape-parse', cause: parsed.error },
|
|
218
224
|
});
|
|
219
225
|
}
|
|
220
|
-
const
|
|
221
|
-
|
|
226
|
+
const drawCalls = countDrawCalls(parsed.value);
|
|
227
|
+
const resource =
|
|
228
|
+
capture.resource !== undefined &&
|
|
229
|
+
capture.resource.observation === undefined &&
|
|
230
|
+
capture.resource.ownerFacts !== undefined &&
|
|
231
|
+
resourceSubjectDrawn(capture.resource, drawCalls)
|
|
232
|
+
? { ...capture.resource, observation: capture.resource.ownerFacts }
|
|
233
|
+
: capture.resource;
|
|
234
|
+
const subjectDigest = resourceSubjectDigest(resource);
|
|
235
|
+
if (resource !== undefined && subjectDigest === undefined) {
|
|
222
236
|
return err({
|
|
223
237
|
code: 'tool-preview-bootstrap-failed',
|
|
224
238
|
expected: 'the resource owner to publish a subject identity before evidence publication',
|
|
225
239
|
hint: 'repair AssetRegistry owner facts or post-frame observation; recipe and trace are not subject identity',
|
|
226
|
-
detail: {
|
|
240
|
+
detail: {
|
|
241
|
+
phase: 'resource-identity',
|
|
242
|
+
cause: {
|
|
243
|
+
kind: resource.kind,
|
|
244
|
+
drawCalls,
|
|
245
|
+
ownerFactsPublished: resource.ownerFacts !== undefined,
|
|
246
|
+
observationPublished: resource.observation !== undefined,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
227
249
|
});
|
|
228
250
|
}
|
|
229
251
|
let runtime: Awaited<ReturnType<typeof createBrowserRhiDebugRuntime>>;
|
|
@@ -237,7 +259,7 @@ export async function replayToolPreviewCapture(
|
|
|
237
259
|
detail: { phase: 'replay-runtime', cause },
|
|
238
260
|
});
|
|
239
261
|
}
|
|
240
|
-
const replayDevice = await runtime.createReplayDevice();
|
|
262
|
+
const replayDevice = await runtime.createReplayDevice(parsed.value);
|
|
241
263
|
if (!replayDevice.ok) {
|
|
242
264
|
return err({
|
|
243
265
|
code: 'tool-preview-capability-unavailable',
|
|
@@ -259,7 +281,6 @@ export async function replayToolPreviewCapture(
|
|
|
259
281
|
});
|
|
260
282
|
}
|
|
261
283
|
const replay = replayResult.value;
|
|
262
|
-
const drawCalls = countDrawCalls(parsed.value);
|
|
263
284
|
if (drawCalls === 0) {
|
|
264
285
|
await replay.dispose();
|
|
265
286
|
return err({
|
|
@@ -507,7 +528,7 @@ export async function replayToolPreviewCapture(
|
|
|
507
528
|
},
|
|
508
529
|
},
|
|
509
530
|
},
|
|
510
|
-
...(
|
|
531
|
+
...(resource === undefined ? {} : { resource }),
|
|
511
532
|
});
|
|
512
533
|
}
|
|
513
534
|
|
|
@@ -673,7 +694,7 @@ export async function createToolPreviewHost(
|
|
|
673
694
|
});
|
|
674
695
|
const executeStartedAtMs = performance.now();
|
|
675
696
|
const actionTrace: ToolPreviewAction[] = [];
|
|
676
|
-
|
|
697
|
+
let encodedCapture: ReturnType<typeof runtime.attachment.captureFrame> | undefined;
|
|
677
698
|
for (let frame = 0; frame < recipe.frames; frame += 1) {
|
|
678
699
|
for (const action of recipe.actions.filter((candidate) => candidate.frame === frame)) {
|
|
679
700
|
let accepted = false;
|
|
@@ -697,6 +718,17 @@ export async function createToolPreviewHost(
|
|
|
697
718
|
}
|
|
698
719
|
actionTrace.push(action);
|
|
699
720
|
}
|
|
721
|
+
if (frame === recipe.frames - 1) {
|
|
722
|
+
encodedCapture = runtime.attachment.captureFrame();
|
|
723
|
+
const snapshot = await runtime.attachment.frameBoundary();
|
|
724
|
+
if (!snapshot.ok)
|
|
725
|
+
return err({
|
|
726
|
+
code: 'tool-preview-bootstrap-failed',
|
|
727
|
+
expected: 'RHI-debug snapshots live resources before the captured frame',
|
|
728
|
+
hint: snapshot.error.hint,
|
|
729
|
+
detail: { phase: 'rhi-snapshot', cause: snapshot.error },
|
|
730
|
+
});
|
|
731
|
+
}
|
|
700
732
|
const stepped = app.stepFrame(recipe.deltaSeconds);
|
|
701
733
|
if (!stepped.ok)
|
|
702
734
|
return err({
|
|
@@ -710,12 +742,14 @@ export async function createToolPreviewHost(
|
|
|
710
742
|
// only the feature's intentional `next-frame` pending state.
|
|
711
743
|
await new Promise<void>((resolve) => setTimeout(resolve, 0));
|
|
712
744
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
745
|
+
const finalized = await runtime.attachment.frameBoundary();
|
|
746
|
+
if (!finalized.ok)
|
|
747
|
+
return err({
|
|
748
|
+
code: 'tool-preview-bootstrap-failed',
|
|
749
|
+
expected: 'RHI-debug finalizes the captured frame',
|
|
750
|
+
hint: finalized.error.hint,
|
|
751
|
+
detail: { phase: 'rhi-finalize', cause: finalized.error },
|
|
752
|
+
});
|
|
719
753
|
if (options.collectResourceFacts !== undefined) {
|
|
720
754
|
try {
|
|
721
755
|
const collected = await options.collectResourceFacts(app, resourceFacts);
|
|
@@ -744,6 +778,14 @@ export async function createToolPreviewHost(
|
|
|
744
778
|
detail: { phase: 'profiler-finish', cause: profile.error },
|
|
745
779
|
});
|
|
746
780
|
}
|
|
781
|
+
if (encodedCapture === undefined) {
|
|
782
|
+
return err({
|
|
783
|
+
code: 'tool-preview-bootstrap-failed',
|
|
784
|
+
expected: 'a positive-frame recipe to arm one captured frame',
|
|
785
|
+
hint: 'validate the recipe before running the preview host',
|
|
786
|
+
detail: { phase: 'rhi-capture' },
|
|
787
|
+
});
|
|
788
|
+
}
|
|
747
789
|
const tape = await encodedCapture;
|
|
748
790
|
if (!tape.ok)
|
|
749
791
|
return err({
|