@forgeax/engine-app 0.1.4 → 0.1.7
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/README.md +20 -14
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/create-app-error-retention.integration.test.d.ts +2 -0
- package/dist/__tests__/create-app-error-retention.integration.test.d.ts.map +1 -0
- package/dist/__tests__/create-app-physics-plugin-failure.integration.test.d.ts +2 -0
- package/dist/__tests__/create-app-physics-plugin-failure.integration.test.d.ts.map +1 -0
- package/dist/animation-asset-lookup.d.ts +1 -2
- package/dist/animation-asset-lookup.d.ts.map +1 -1
- package/dist/browser-frame-signal.d.ts +17 -0
- package/dist/browser-frame-signal.d.ts.map +1 -0
- package/dist/create-app.d.ts +31 -10
- package/dist/create-app.d.ts.map +1 -1
- package/dist/engine-worker-runtime.mjs +72 -129
- package/dist/engine-worker-runtime.mjs.map +1 -1
- package/dist/errors.d.ts +3 -12
- package/dist/errors.d.ts.map +1 -1
- package/dist/execution/attached-world-swap.d.ts +1 -12
- package/dist/execution/attached-world-swap.d.ts.map +1 -1
- package/dist/execution/bootstrap-url.d.ts +5 -0
- package/dist/execution/bootstrap-url.d.ts.map +1 -0
- package/dist/execution/control.d.ts +0 -2
- package/dist/execution/control.d.ts.map +1 -1
- package/dist/execution/engine-worker.d.ts +1 -0
- package/dist/execution/engine-worker.d.ts.map +1 -1
- package/dist/execution/host-controller.d.ts.map +1 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/protocol.d.ts +4 -1
- package/dist/execution/protocol.d.ts.map +1 -1
- package/dist/execution/types.d.ts +17 -1
- package/dist/execution/types.d.ts.map +1 -1
- package/dist/game-context.d.ts +1 -1
- package/dist/game-context.d.ts.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +357 -359
- package/dist/index.mjs.map +1 -1
- package/dist/internal/assembled-engine-profile.d.ts.map +1 -1
- package/dist/internal/assets-world-plugin.d.ts +3 -17
- package/dist/internal/assets-world-plugin.d.ts.map +1 -1
- package/dist/internal/browser-remote-bridge.d.ts +1 -2
- package/dist/internal/browser-remote-bridge.d.ts.map +1 -1
- package/dist/internal/browser-rhi-debug-runtime.d.ts +1 -1
- package/dist/internal/browser-rhi-debug-runtime.d.ts.map +1 -1
- package/dist/internal/debug-draw.d.ts +9 -0
- package/dist/internal/debug-draw.d.ts.map +1 -0
- package/dist/internal/engine-profile-common.d.ts +2 -2
- package/dist/internal/engine-profile-common.d.ts.map +1 -1
- package/dist/internal/frame-loop.d.ts +7 -4
- package/dist/internal/frame-loop.d.ts.map +1 -1
- package/dist/internal/main-engine-profile.d.ts +4 -0
- package/dist/internal/main-engine-profile.d.ts.map +1 -1
- package/dist/internal/remote-serve-flag.d.ts +3 -7
- package/dist/internal/remote-serve-flag.d.ts.map +1 -1
- package/dist/internal/rhi-capture.d.ts +1 -1
- package/dist/internal/rhi-capture.d.ts.map +1 -1
- package/dist/internal/worker-engine-profile.d.ts +2 -0
- package/dist/internal/worker-engine-profile.d.ts.map +1 -1
- package/dist/renderer-plugin.d.ts +25 -0
- package/dist/renderer-plugin.d.ts.map +1 -0
- package/dist/tool-preview/bootstrap.d.ts.map +1 -1
- package/dist/types.d.ts +21 -61
- package/dist/types.d.ts.map +1 -1
- package/package.json +25 -26
- package/src/__tests__/callback-inference.test-d.ts +7 -3
- package/src/__tests__/consumer-migration.unit.test.ts +13 -0
- package/src/__tests__/create-app-error-retention.integration.test.ts +125 -0
- package/src/__tests__/create-app-features.test.ts +21 -10
- package/src/__tests__/create-app-listener-sync.test.ts +23 -19
- package/src/__tests__/create-app-physics-plugin-failure.integration.test.ts +142 -0
- package/src/__tests__/create-app-stop.test.ts +4 -12
- package/src/__tests__/create-app.test-d.ts +12 -11
- package/src/__tests__/create-app.test.ts +1 -60
- package/src/__tests__/create-renderer-error.integration.test.ts +3 -2
- package/src/__tests__/create-renderer-lifecycle.integration.test.ts +10 -5
- package/src/__tests__/draw-source-injected-world-update-visibility.test.ts +7 -13
- package/src/__tests__/draw-source-single-world-regression.test.ts +23 -24
- package/src/__tests__/engine-worker-bootstrap-channel.unit.test.ts +8 -0
- package/src/__tests__/engine-worker-world-swap.unit.test.ts +15 -22
- package/src/__tests__/errors-pointer-lock-failed.test.ts +4 -7
- package/src/__tests__/execution-bootstrap-isolation.unit.test.ts +5 -6
- package/src/__tests__/execution-frame-order.unit.test.ts +2 -2
- package/src/__tests__/execution-frame-protocol.unit.test.ts +3 -4
- package/src/__tests__/execution-public-api.test-d.ts +4 -0
- package/src/__tests__/frame-loop-time-elapsed.test.ts +1 -1
- package/src/__tests__/frame-loop-time.unit.test.ts +1 -1
- package/src/__tests__/frame-loop-world-array.test.ts +82 -73
- package/src/__tests__/plugin-profiles.unit.test.ts +3 -3
- package/src/__tests__/profiler-default-off.test.ts +1 -1
- package/src/__tests__/profiler-frame-token.test.ts +17 -30
- package/src/__tests__/profiler-phase-integration.test.ts +15 -27
- package/src/__tests__/surface-handoff.test.ts +1 -4
- package/src/__tests__/visibility-remote.integration.test.ts +2 -5
- package/src/__tests__/worker-execution-stop.test.ts +64 -7
- package/src/animation-asset-lookup.ts +2 -2
- package/src/browser-frame-signal.ts +44 -0
- package/src/create-app.ts +208 -295
- package/src/errors.ts +27 -39
- package/src/execution/attached-world-swap.ts +4 -38
- package/src/execution/bootstrap-url.ts +25 -0
- package/src/execution/control.ts +3 -7
- package/src/execution/engine-worker-runtime.ts +23 -40
- package/src/execution/engine-worker.ts +2 -0
- package/src/execution/host-controller.ts +8 -2
- package/src/execution/index.ts +1 -0
- package/src/execution/protocol.ts +4 -1
- package/src/execution/types.ts +18 -1
- package/src/game-context.ts +1 -1
- package/src/index.ts +18 -4
- package/src/internal/assembled-engine-profile.ts +3 -11
- package/src/internal/assets-world-plugin.ts +7 -53
- package/src/internal/browser-remote-bridge.ts +2 -3
- package/src/internal/browser-rhi-debug-runtime.ts +1 -1
- package/src/internal/debug-draw.ts +38 -0
- package/src/internal/engine-profile-common.ts +2 -3
- package/src/internal/frame-loop.ts +77 -63
- package/src/internal/main-engine-profile.ts +21 -17
- package/src/internal/remote-serve-flag.ts +5 -14
- package/src/internal/rhi-capture.ts +1 -1
- package/src/internal/worker-engine-profile.ts +10 -10
- package/src/renderer-plugin.ts +96 -0
- package/src/tool-preview/bootstrap.ts +1 -14
- package/src/types.ts +22 -77
- package/src/vite-env.d.ts +0 -2
- package/dist/__tests__/app-rebuild.test.d.ts +0 -2
- package/dist/__tests__/app-rebuild.test.d.ts.map +0 -1
- package/dist/__tests__/asset-registry-types.test-d.d.ts +0 -2
- package/dist/__tests__/asset-registry-types.test-d.d.ts.map +0 -1
- package/dist/__tests__/assets-runtime-assembly.integration.test.d.ts +0 -2
- package/dist/__tests__/assets-runtime-assembly.integration.test.d.ts.map +0 -1
- package/dist/__tests__/draw-source-headless-full-chain.test.d.ts +0 -2
- package/dist/__tests__/draw-source-headless-full-chain.test.d.ts.map +0 -1
- package/dist/__tests__/ecs-import.unit.test.d.ts +0 -2
- package/dist/__tests__/ecs-import.unit.test.d.ts.map +0 -1
- package/dist/__tests__/execution-world-health-owner.test-d.d.ts +0 -2
- package/dist/__tests__/execution-world-health-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/remote-serve-flag.test.d.ts +0 -2
- package/dist/__tests__/remote-serve-flag.test.d.ts.map +0 -1
- package/dist/assets-runtime-assembly.d.ts +0 -19
- package/dist/assets-runtime-assembly.d.ts.map +0 -1
- package/src/__tests__/app-rebuild.test.ts +0 -31
- package/src/__tests__/asset-registry-types.test-d.ts +0 -16
- package/src/__tests__/assets-runtime-assembly.integration.test.ts +0 -68
- package/src/__tests__/draw-source-headless-full-chain.test.ts +0 -226
- package/src/__tests__/ecs-import.unit.test.ts +0 -40
- package/src/__tests__/execution-world-health-owner.test-d.ts +0 -9
- package/src/__tests__/remote-serve-flag.test.ts +0 -24
- package/src/assets-runtime-assembly.ts +0 -70
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Plugin } from '@forgeax/engine-plugin';
|
|
2
|
+
import type { RenderError, Renderer, RenderFeature, RenderResult } from '@forgeax/engine-render';
|
|
3
|
+
import type { RendererFeatureAssemblyHost } from '@forgeax/engine-render/internal/construct-renderer';
|
|
4
|
+
|
|
5
|
+
export interface RenderFeatureHost {
|
|
6
|
+
installFeature(
|
|
7
|
+
feature: RenderFeature<unknown>,
|
|
8
|
+
): Promise<RenderResult<RenderFeatureLease, RenderError>>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RenderFeatureLease {
|
|
12
|
+
release(): Promise<RenderResult<void, RenderError>>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function createRenderFeatureHost(host: RendererFeatureAssemblyHost): RenderFeatureHost {
|
|
16
|
+
return {
|
|
17
|
+
async installFeature(feature) {
|
|
18
|
+
const installed = await host.installRenderFeature(feature);
|
|
19
|
+
if (!installed.ok) return installed;
|
|
20
|
+
let released = false;
|
|
21
|
+
return {
|
|
22
|
+
ok: true,
|
|
23
|
+
value: {
|
|
24
|
+
release: async () => {
|
|
25
|
+
if (released) return { ok: true, value: undefined };
|
|
26
|
+
released = true;
|
|
27
|
+
return host.uninstallRenderFeature(feature);
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
declare module '@forgeax/engine-plugin' {
|
|
36
|
+
interface EngineContextServices {
|
|
37
|
+
renderer?: Renderer;
|
|
38
|
+
renderFeatureHost?: RenderFeatureHost;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Provide the renderer without transferring its host-owned lifetime. */
|
|
43
|
+
export function rendererPlugin(renderer: Renderer): Plugin {
|
|
44
|
+
return {
|
|
45
|
+
name: 'renderer',
|
|
46
|
+
provide: 'renderer',
|
|
47
|
+
apply(ctx) {
|
|
48
|
+
ctx.provide('renderer', renderer);
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Provide an App/Worker-owned Renderer and release it after dependent Fibers. */
|
|
54
|
+
export function ownedRendererPlugin(renderer: Renderer): Plugin {
|
|
55
|
+
return {
|
|
56
|
+
name: 'renderer',
|
|
57
|
+
provide: 'renderer',
|
|
58
|
+
apply(ctx) {
|
|
59
|
+
ctx.provide('renderer', renderer);
|
|
60
|
+
ctx.effect(() => () => renderer.dispose(), 'render/renderer');
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Provide the App-owned late RenderFeature assembly capability. */
|
|
66
|
+
export function renderFeatureHostPlugin(host: RenderFeatureHost): Plugin {
|
|
67
|
+
return {
|
|
68
|
+
name: 'render-feature-host',
|
|
69
|
+
provide: 'renderFeatureHost',
|
|
70
|
+
apply(ctx) {
|
|
71
|
+
ctx.provide('renderFeatureHost', host);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Install a producer feature under the same Cordis Fiber that owns the caller. */
|
|
77
|
+
export function renderFeaturePlugin(feature: RenderFeature<unknown>): Plugin {
|
|
78
|
+
return {
|
|
79
|
+
name: `render-feature:${feature.identity}`,
|
|
80
|
+
inject: ['renderFeatureHost'],
|
|
81
|
+
async apply(ctx) {
|
|
82
|
+
if (ctx.renderFeatureHost === undefined) {
|
|
83
|
+
throw new Error('render-feature host capability is unavailable in this App realm');
|
|
84
|
+
}
|
|
85
|
+
const installed = await ctx.renderFeatureHost.installFeature(feature);
|
|
86
|
+
if (!installed.ok) throw installed.error;
|
|
87
|
+
ctx.effect(
|
|
88
|
+
() => async () => {
|
|
89
|
+
const removed = await installed.value.release();
|
|
90
|
+
if (!removed.ok) throw removed.error;
|
|
91
|
+
},
|
|
92
|
+
`render-feature/${feature.identity}`,
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -586,19 +586,6 @@ export async function createToolPreviewHost(
|
|
|
586
586
|
const app = appResult.value;
|
|
587
587
|
const appErrors: unknown[] = [];
|
|
588
588
|
const unsubscribeAppErrors = app.onError((error) => appErrors.push(error));
|
|
589
|
-
const rendererReady = await app.renderer.ready;
|
|
590
|
-
if (!rendererReady.ok) {
|
|
591
|
-
unsubscribeAppErrors();
|
|
592
|
-
await app.dispose();
|
|
593
|
-
await runtime.attachment.dispose();
|
|
594
|
-
removeOwnedCanvas(canvas, ownsCanvas);
|
|
595
|
-
return err({
|
|
596
|
-
code: 'tool-preview-bootstrap-failed',
|
|
597
|
-
expected: 'the real WebGPU Renderer to finish pipeline initialization before preview frames',
|
|
598
|
-
hint: rendererReady.error.hint,
|
|
599
|
-
detail: { phase: 'renderer-ready', cause: rendererReady.error },
|
|
600
|
-
});
|
|
601
|
-
}
|
|
602
589
|
let resourceFacts: ToolPreviewResourceFacts | undefined;
|
|
603
590
|
try {
|
|
604
591
|
const prepared = await options.prepare?.(app);
|
|
@@ -626,7 +613,7 @@ export async function createToolPreviewHost(
|
|
|
626
613
|
detail: { phase: bootstrapFailure.phase, cause },
|
|
627
614
|
});
|
|
628
615
|
}
|
|
629
|
-
const attached = app.renderer.
|
|
616
|
+
const attached = app.renderer.attach(app.world);
|
|
630
617
|
if (!attached.ok) {
|
|
631
618
|
unsubscribeAppErrors();
|
|
632
619
|
await app.dispose();
|
package/src/types.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// loop, dt clamp, error fan-out, and input attach internals land in
|
|
10
10
|
// later milestones (M2..M5 per plan-strategy section 7).
|
|
11
11
|
|
|
12
|
-
import type { AssetRegistry
|
|
12
|
+
import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
13
13
|
import type { AudioBackend } from '@forgeax/engine-audio';
|
|
14
14
|
import type { DebugDraw } from '@forgeax/engine-debug-draw';
|
|
15
15
|
import type { TimePolicy, World } from '@forgeax/engine-ecs';
|
|
@@ -22,18 +22,12 @@ import type {
|
|
|
22
22
|
import type { PhysicsWorld, PhysicsWorld2D } from '@forgeax/engine-physics';
|
|
23
23
|
import type { Context, Plugin } from '@forgeax/engine-plugin';
|
|
24
24
|
import type { Profiler } from '@forgeax/engine-profiler';
|
|
25
|
-
import type {
|
|
26
|
-
|
|
27
|
-
Renderer,
|
|
28
|
-
RendererError,
|
|
29
|
-
RenderFeature,
|
|
30
|
-
} from '@forgeax/engine-render';
|
|
31
|
-
import type { RhiBackendInstrumentation } from '@forgeax/engine-render/internal';
|
|
25
|
+
import type { RenderError, Renderer, RenderFeature, RenderProfile } from '@forgeax/engine-render';
|
|
26
|
+
import type { RhiBackendInstrumentation } from '@forgeax/engine-render/internal/construct-renderer';
|
|
32
27
|
import type { RhiError, RhiInstance } from '@forgeax/engine-rhi';
|
|
33
|
-
import type { CaptureFrameOptions, RhiDebugError } from '@forgeax/engine-rhi-debug';
|
|
34
28
|
import type { EngineEnvironmentError } from '@forgeax/engine-runtime';
|
|
35
|
-
import type {
|
|
36
|
-
|
|
29
|
+
import type { ImportTransport, Result } from '@forgeax/engine-types';
|
|
30
|
+
|
|
37
31
|
import type { AppError, AppErrorCode } from './errors';
|
|
38
32
|
import type { ExecutionControl, ExecutionOptions } from './execution';
|
|
39
33
|
import type { RhiCapture } from './internal/rhi-capture';
|
|
@@ -58,7 +52,7 @@ export type { AppError, AppErrorCode };
|
|
|
58
52
|
* `RhiErrorCode` / per-cluster `*ErrorCode` / `PostProcessErrorCode` literal
|
|
59
53
|
* sets let TS narrow each arm to the concrete class.
|
|
60
54
|
*/
|
|
61
|
-
export type AppDispatchError = AppError |
|
|
55
|
+
export type AppDispatchError = AppError | RenderError;
|
|
62
56
|
|
|
63
57
|
/**
|
|
64
58
|
* Per-frame draw description pulled from the host each frame
|
|
@@ -137,11 +131,9 @@ export type DrawSource = () => DrawSourceResult | undefined;
|
|
|
137
131
|
*/
|
|
138
132
|
export interface AppAssembleArgs {
|
|
139
133
|
readonly renderer: Renderer;
|
|
134
|
+
/** Host-owned asset catalogue paired with the renderer construction. */
|
|
135
|
+
readonly assets?: AssetRegistry;
|
|
140
136
|
readonly world: World;
|
|
141
|
-
/** One immutable Catalog scope for this App realm. */
|
|
142
|
-
readonly assetCatalog?: CatalogSource;
|
|
143
|
-
/** Explicit owner contributions installed into this realm's Registry. */
|
|
144
|
-
readonly assetDecoders?: readonly AssetDecoderContributionRef[];
|
|
145
137
|
/** Unified plugin list (M1 feat-20260623-plugin-system-unify-build-world-protocol). */
|
|
146
138
|
readonly plugins?: readonly Plugin[];
|
|
147
139
|
readonly silenceUnhandledErrors?: boolean;
|
|
@@ -154,8 +146,6 @@ export interface AppAssembleArgs {
|
|
|
154
146
|
readonly drawSource?: DrawSource;
|
|
155
147
|
/** Explicit profiler capability shared by the host and renderer. */
|
|
156
148
|
readonly profiler?: Profiler;
|
|
157
|
-
/** Explicit opt-in for Render-owned HDRP membership timing evidence. */
|
|
158
|
-
readonly membershipTiming?: MembershipTimingOptions;
|
|
159
149
|
}
|
|
160
150
|
|
|
161
151
|
/** Effective physical canvas size transported to an Engine Worker frame. */
|
|
@@ -169,8 +159,8 @@ export interface CanvasDrawingBufferSize {
|
|
|
169
159
|
*
|
|
170
160
|
* feat-20260608-create-app-param-surface-trim / M2 / D-3: self-describing
|
|
171
161
|
* surface -- no longer `extends RendererOptions`. The 7 app-only fields
|
|
172
|
-
* (input / audio / physics / silenceUnhandledErrors) plus the
|
|
173
|
-
*
|
|
162
|
+
* (input / audio / physics / silenceUnhandledErrors) plus the RHI escape-hatch
|
|
163
|
+
* field (rhi) are
|
|
174
164
|
* listed inline, so IDE autocomplete shows AI users a clean surface
|
|
175
165
|
* without inheriting now-disallowed slots like clearColor (M1, on Camera)
|
|
176
166
|
* and shaderManifestUrl (M2, on BundlerOptions / 3rd arg). The escape
|
|
@@ -178,23 +168,14 @@ export interface CanvasDrawingBufferSize {
|
|
|
178
168
|
* default noise, but reachable when the AI user scrolls the type).
|
|
179
169
|
*/
|
|
180
170
|
export interface CreateAppOptions {
|
|
181
|
-
/**
|
|
182
|
-
* Optional positive Host-owned upper bound for the canvas device pixel ratio.
|
|
183
|
-
* Values below 1 intentionally downsample GPU-bound surfaces. The default is
|
|
184
|
-
* the current devicePixelRatio; the Engine never reads URL or game-specific
|
|
185
|
-
* settings to derive this value.
|
|
186
|
-
*/
|
|
187
|
-
readonly maxCanvasPixelRatio?: number | undefined;
|
|
188
|
-
/** One immutable Catalog scope for this App realm. */
|
|
189
|
-
readonly assetCatalog?: CatalogSource;
|
|
190
|
-
/** Explicit owner contributions installed into this realm's Registry. */
|
|
191
|
-
readonly assetDecoders?: readonly AssetDecoderContributionRef[];
|
|
192
171
|
/** Opt into realm-local engine execution. Omission preserves the existing local assembly path. */
|
|
193
172
|
readonly execution?: ExecutionOptions;
|
|
194
173
|
/** Host-owned UI root whose events do not enter gameplay input. */
|
|
195
174
|
readonly uiRoot?: Node;
|
|
196
175
|
/** Producer-owned render features forwarded to the renderer unchanged. */
|
|
197
176
|
readonly features?: readonly RenderFeature<unknown>[];
|
|
177
|
+
/** Standard profile forwarded to the single renderer-owned pipeline. */
|
|
178
|
+
readonly standardProfile?: RenderProfile;
|
|
198
179
|
/** Unified plugin list (M1 feat-20260623-plugin-system-unify-build-world-protocol). */
|
|
199
180
|
readonly plugins?: readonly Plugin[];
|
|
200
181
|
/**
|
|
@@ -220,15 +201,8 @@ export interface CreateAppOptions {
|
|
|
220
201
|
* advanced AI users that ship their own RhiInstance shim.
|
|
221
202
|
*/
|
|
222
203
|
readonly rhi?: RhiInstance | undefined;
|
|
223
|
-
/**
|
|
204
|
+
/** Optional host-owned RHI lifecycle instrumentation, such as recording. */
|
|
224
205
|
readonly rhiInstrumentation?: RhiBackendInstrumentation;
|
|
225
|
-
/**
|
|
226
|
-
* D-S1 raw GPUDevice escape hatch -- forwarded verbatim to createRenderer.
|
|
227
|
-
* Same semantics as `RendererOptions.rawDeviceForContextConfigure`. Used
|
|
228
|
-
* by the apps/hello/triangle bootstrap, where the host configures the
|
|
229
|
-
* canvas's GPUCanvasContext outside the RHI surface.
|
|
230
|
-
*/
|
|
231
|
-
readonly rawDeviceForContextConfigure?: unknown | (() => unknown | undefined);
|
|
232
206
|
/**
|
|
233
207
|
* Neutral PointerLock gate forwarded verbatim to the canvas-form input
|
|
234
208
|
* attach (attachInputAuto → attachBrowserInputBackend). When it returns
|
|
@@ -279,8 +253,6 @@ export interface CreateAppOptions {
|
|
|
279
253
|
readonly drawSource?: DrawSource;
|
|
280
254
|
/** Explicit profiler capability shared by the host and renderer. */
|
|
281
255
|
readonly profiler?: Profiler;
|
|
282
|
-
/** Explicit opt-in for Render-owned HDRP membership timing evidence. */
|
|
283
|
-
readonly membershipTiming?: MembershipTimingOptions;
|
|
284
256
|
}
|
|
285
257
|
|
|
286
258
|
/**
|
|
@@ -345,8 +317,8 @@ export interface BundlerOptions {
|
|
|
345
317
|
export interface App {
|
|
346
318
|
/** Caller-owned Renderer (reference equality with the assemble input). */
|
|
347
319
|
readonly renderer: Renderer;
|
|
348
|
-
/**
|
|
349
|
-
readonly assets
|
|
320
|
+
/** Host-owned asset catalogue paired with this renderer lease. */
|
|
321
|
+
readonly assets?: AssetRegistry;
|
|
350
322
|
/** Caller-owned World (reference equality with the assemble input). */
|
|
351
323
|
readonly world: World;
|
|
352
324
|
/** Host-side lifecycle and immutable diagnostics for the selected execution tier. */
|
|
@@ -355,9 +327,9 @@ export interface App {
|
|
|
355
327
|
* Pause frame submission and relinquish the renderer presentation surface
|
|
356
328
|
* without replacing World, Renderer, AssetRegistry, plugins, or history.
|
|
357
329
|
*/
|
|
358
|
-
releaseSurfacePreserveWorld(): Promise<Result<void, RhiError>>;
|
|
330
|
+
releaseSurfacePreserveWorld(): Promise<Result<void, RhiError | RenderError>>;
|
|
359
331
|
/** Restore the same surface and resume only when release paused a running App. */
|
|
360
|
-
restoreSurface(): Promise<Result<void, RhiError>>;
|
|
332
|
+
restoreSurface(): Promise<Result<void, RhiError | RenderError>>;
|
|
361
333
|
/** Native Cordis realm that owns this App's capability fibers and effects. */
|
|
362
334
|
readonly pluginContext: Context;
|
|
363
335
|
/** InputBackend handle when input attach is enabled; undefined otherwise. */
|
|
@@ -432,18 +404,12 @@ export interface App {
|
|
|
432
404
|
*/
|
|
433
405
|
setDrawSource(drawSource: DrawSource | undefined): void;
|
|
434
406
|
/**
|
|
435
|
-
* Most recent
|
|
407
|
+
* Most recent dispatched error retained for host self-inspection without
|
|
436
408
|
* requiring an onError listener up front.
|
|
437
409
|
*/
|
|
438
410
|
readonly lastError?: AppDispatchError | undefined;
|
|
439
|
-
/**
|
|
440
|
-
|
|
441
|
-
*
|
|
442
|
-
* A successful capture returns one `{ kind: 'rhi-tape', digest, bytes }`
|
|
443
|
-
* artifact. Pass that same artifact to DevKit summary and inspect
|
|
444
|
-
* operations; the selection key is `FrameModel.works[].workIndex`.
|
|
445
|
-
*/
|
|
446
|
-
readonly rhiCapture?: RhiCapture | undefined;
|
|
411
|
+
/** Optional single-frame RHI capture capability owned by the App host. */
|
|
412
|
+
readonly rhiCapture?: RhiCapture;
|
|
447
413
|
/**
|
|
448
414
|
* Handle for the remote eval server started by createApp (dev mode).
|
|
449
415
|
*
|
|
@@ -461,30 +427,9 @@ export interface App {
|
|
|
461
427
|
/** Host control returned by the unified execution path. Engine-owned objects remain realm-local. */
|
|
462
428
|
export type ExecutionApp = Pick<
|
|
463
429
|
App,
|
|
464
|
-
| '
|
|
465
|
-
| 'input'
|
|
466
|
-
| 'audio'
|
|
467
|
-
| 'rhiCapture'
|
|
468
|
-
| 'start'
|
|
469
|
-
| 'stop'
|
|
470
|
-
| 'pause'
|
|
471
|
-
| 'resume'
|
|
472
|
-
| 'onError'
|
|
473
|
-
| 'lastError'
|
|
430
|
+
'execution' | 'input' | 'audio' | 'start' | 'stop' | 'pause' | 'resume' | 'onError' | 'lastError'
|
|
474
431
|
>;
|
|
475
432
|
|
|
476
|
-
/** Artifact returned by the browser RHI-debug capture capability. */
|
|
477
|
-
export interface RhiCaptureArtifact {
|
|
478
|
-
readonly kind: 'rhi-tape';
|
|
479
|
-
readonly digest: string;
|
|
480
|
-
readonly bytes: Uint8Array;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
/** Same-origin browser hook shared by main-serial and Worker execution. */
|
|
484
|
-
export interface RhiCaptureHook {
|
|
485
|
-
captureFrame(options?: CaptureFrameOptions): Promise<Result<RhiCaptureArtifact, RhiDebugError>>;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
433
|
/**
|
|
489
434
|
* Error union returned by the assemble-form entry. The canvas-form thin
|
|
490
435
|
* wrapper widens this with EngineEnvironmentError (createRenderer
|
|
@@ -492,7 +437,7 @@ export interface RhiCaptureHook {
|
|
|
492
437
|
*
|
|
493
438
|
* Cordis activation failures are projected into AppError at this boundary.
|
|
494
439
|
*/
|
|
495
|
-
export type AssembleAppError = AppError | RhiError
|
|
440
|
+
export type AssembleAppError = AppError | RhiError;
|
|
496
441
|
|
|
497
442
|
/**
|
|
498
443
|
* Error union returned by the canvas-form thin wrapper. Extends
|
package/src/vite-env.d.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"app-rebuild.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/app-rebuild.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"asset-registry-types.test-d.d.ts","sourceRoot":"","sources":["../../src/__tests__/asset-registry-types.test-d.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"assets-runtime-assembly.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/assets-runtime-assembly.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"draw-source-headless-full-chain.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/draw-source-headless-full-chain.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ecs-import.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ecs-import.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"execution-world-health-owner.test-d.d.ts","sourceRoot":"","sources":["../../src/__tests__/execution-world-health-owner.test-d.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remote-serve-flag.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/remote-serve-flag.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { AssetDecoderLease, AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
2
|
-
import { type AssetDecoderContributionRef, type Result } from '@forgeax/engine-types';
|
|
3
|
-
export interface AssetRuntimeAssemblyError {
|
|
4
|
-
readonly code: 'asset-assembly-failed';
|
|
5
|
-
readonly expected: string;
|
|
6
|
-
readonly hint: string;
|
|
7
|
-
readonly detail: {
|
|
8
|
-
readonly kind: string;
|
|
9
|
-
readonly cause: unknown;
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
export interface AssetRuntimeAssembly {
|
|
13
|
-
readonly registry: AssetRegistry;
|
|
14
|
-
readonly leases: readonly AssetDecoderLease[];
|
|
15
|
-
dispose(): void;
|
|
16
|
-
}
|
|
17
|
-
/** Install owner decoder contributions into the realm's one asset registry. */
|
|
18
|
-
export declare function assembleAssetRuntime(registry: AssetRegistry, contributions: readonly AssetDecoderContributionRef[]): Result<AssetRuntimeAssembly, AssetRuntimeAssemblyError>;
|
|
19
|
-
//# sourceMappingURL=assets-runtime-assembly.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"assets-runtime-assembly.d.ts","sourceRoot":"","sources":["../src/assets-runtime-assembly.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAEvF,OAAO,EACL,KAAK,2BAA2B,EAIhC,KAAK,MAAM,EACZ,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;CACrE;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC9C,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,aAAa,EACvB,aAAa,EAAE,SAAS,2BAA2B,EAAE,GACpD,MAAM,CAAC,oBAAoB,EAAE,yBAAyB,CAAC,CA0CzD"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { disposeWithOrderedDetail, RebuildLifecycleError } from '../execution/attached-world-swap';
|
|
3
|
-
|
|
4
|
-
describe('M4 app rebuild lifecycle', () => {
|
|
5
|
-
it('retains primary failure while recording both cleanup failures in order', async () => {
|
|
6
|
-
const cleanup: { phase: 'candidate' | 'previous'; cause: unknown }[] = [];
|
|
7
|
-
const primary = new Error('system throw');
|
|
8
|
-
await disposeWithOrderedDetail(
|
|
9
|
-
'candidate',
|
|
10
|
-
() => {
|
|
11
|
-
throw new Error('candidate cleanup');
|
|
12
|
-
},
|
|
13
|
-
cleanup,
|
|
14
|
-
);
|
|
15
|
-
await disposeWithOrderedDetail(
|
|
16
|
-
'previous',
|
|
17
|
-
() => {
|
|
18
|
-
throw new Error('previous cleanup');
|
|
19
|
-
},
|
|
20
|
-
cleanup,
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
const failure = new RebuildLifecycleError(primary, cleanup);
|
|
24
|
-
expect(failure.primary).toBe(primary);
|
|
25
|
-
expect(failure.cleanup.map((entry) => entry.phase)).toEqual(['candidate', 'previous']);
|
|
26
|
-
expect(failure.cleanup.map((entry) => (entry.cause as Error).message)).toEqual([
|
|
27
|
-
'candidate cleanup',
|
|
28
|
-
'previous cleanup',
|
|
29
|
-
]);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
2
|
-
import type { EngineContextServices } from '@forgeax/engine-plugin';
|
|
3
|
-
import type { RenderAssetPort } from '@forgeax/engine-render';
|
|
4
|
-
import { describe, expectTypeOf, it } from 'vitest';
|
|
5
|
-
import type { App, GameHost } from '../index';
|
|
6
|
-
|
|
7
|
-
describe('app asset ownership types', () => {
|
|
8
|
-
it('keeps the GameHost loader registry distinct from the App render projection', () => {
|
|
9
|
-
expectTypeOf<GameHost['assets']>().toEqualTypeOf<AssetRegistry>();
|
|
10
|
-
expectTypeOf<App['assets']>().toEqualTypeOf<AssetRegistry>();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('augments the engine service with the Renderer-owned port', () => {
|
|
14
|
-
expectTypeOf<EngineContextServices['assets']>().toEqualTypeOf<RenderAssetPort | undefined>();
|
|
15
|
-
});
|
|
16
|
-
});
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createAssetRegistry,
|
|
3
|
-
createCatalogSource,
|
|
4
|
-
defineAssetKind,
|
|
5
|
-
} from '@forgeax/engine-assets-runtime';
|
|
6
|
-
import { ok } from '@forgeax/engine-types';
|
|
7
|
-
import { describe, expect, it } from 'vitest';
|
|
8
|
-
import { assembleAssetRuntime } from '../assets-runtime-assembly';
|
|
9
|
-
|
|
10
|
-
const kind = defineAssetKind<unknown, 'host-blob'>('host-blob');
|
|
11
|
-
|
|
12
|
-
describe('App asset runtime assembly', () => {
|
|
13
|
-
it('installs the one default owner contribution for each durable built-in kind', () => {
|
|
14
|
-
const registry = createAssetRegistry({ catalog: createCatalogSource({ entries: [] }) });
|
|
15
|
-
const assembled = assembleAssetRuntime(registry, []);
|
|
16
|
-
|
|
17
|
-
expect(assembled.ok).toBe(true);
|
|
18
|
-
if (!assembled.ok) return;
|
|
19
|
-
expect(assembled.value.leases.map((lease) => lease.kind)).toEqual([
|
|
20
|
-
'mesh',
|
|
21
|
-
'material',
|
|
22
|
-
'scene',
|
|
23
|
-
'texture',
|
|
24
|
-
'equirect',
|
|
25
|
-
'sampler',
|
|
26
|
-
'font',
|
|
27
|
-
'render-pipeline',
|
|
28
|
-
'tileset',
|
|
29
|
-
'video',
|
|
30
|
-
'skeleton',
|
|
31
|
-
'skin',
|
|
32
|
-
'animation-clip',
|
|
33
|
-
'animation-graph',
|
|
34
|
-
'audio',
|
|
35
|
-
'particle-effect',
|
|
36
|
-
]);
|
|
37
|
-
assembled.value.dispose();
|
|
38
|
-
registry.dispose();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('installs one owner lease and releases it idempotently', () => {
|
|
42
|
-
const registry = createAssetRegistry({ catalog: createCatalogSource({ entries: [] }) });
|
|
43
|
-
const assembled = assembleAssetRuntime(registry, [
|
|
44
|
-
{ kind, consumer: 'test-owner', decoder: { decode: async () => ok('value') } },
|
|
45
|
-
]);
|
|
46
|
-
|
|
47
|
-
expect(assembled.ok).toBe(true);
|
|
48
|
-
if (!assembled.ok) return;
|
|
49
|
-
expect(assembled.value.leases).toHaveLength(17);
|
|
50
|
-
expect(assembled.value.leases.at(-1)?.kind).toBe('host-blob');
|
|
51
|
-
assembled.value.dispose();
|
|
52
|
-
assembled.value.dispose();
|
|
53
|
-
registry.dispose();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('returns a closed assembly error for duplicate owner kinds', () => {
|
|
57
|
-
const registry = createAssetRegistry({ catalog: createCatalogSource({ entries: [] }) });
|
|
58
|
-
const contribution = {
|
|
59
|
-
kind,
|
|
60
|
-
consumer: 'test-owner',
|
|
61
|
-
decoder: { decode: async () => ok('value') },
|
|
62
|
-
};
|
|
63
|
-
const assembled = assembleAssetRuntime(registry, [contribution, contribution]);
|
|
64
|
-
|
|
65
|
-
expect(assembled).toMatchObject({ ok: false, error: { code: 'asset-assembly-failed' } });
|
|
66
|
-
registry.dispose();
|
|
67
|
-
});
|
|
68
|
-
});
|