@forgeax/engine-app 0.1.3 → 0.1.6
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/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 +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +332 -366
- 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/create-app.ts +197 -296
- 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 +11 -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 +12 -10
- 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
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { Update, World, createWorldContext, componentDefinition } from '@forgeax/engine-ecs';
|
|
2
2
|
export { Context } from '@forgeax/engine-plugin';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import { err, ok } from '@forgeax/engine-types';
|
|
6
|
-
import { createAssetRegistry, createCatalogSource } from '@forgeax/engine-assets-runtime';
|
|
7
|
-
import { getAssetRegistryResolver } from '@forgeax/engine-assets-runtime/internal';
|
|
8
|
-
import { loadRhiPack, createDebugDrawOnReady, releaseDebugDraw } from '@forgeax/engine-render/internal';
|
|
3
|
+
export { createFullscreenRenderFeature } from '@forgeax/engine-render/authoring';
|
|
4
|
+
import { Camera, perspective, renderComponentsPlugin, CAMERA_PROJECTION_PERSPECTIVE } from '@forgeax/engine-render';
|
|
9
5
|
import { RhiError } from '@forgeax/engine-rhi';
|
|
10
|
-
import {
|
|
6
|
+
import { attachRecorder, decodeTape, openReplay, decodeToRgba8, buildTapeIndex, createRhiDebugError } from '@forgeax/engine-rhi-debug';
|
|
7
|
+
import * as engineRuntimeModule from '@forgeax/engine-runtime';
|
|
8
|
+
import { EngineEnvironmentError } from '@forgeax/engine-runtime';
|
|
9
|
+
import { loadRhiPack, constructRuntimeRendererHost } from '@forgeax/engine-runtime/internal/renderer-host';
|
|
10
|
+
import { ok, err } from '@forgeax/engine-types';
|
|
11
11
|
import { createHostAudioConsumer } from '@forgeax/engine-audio-webaudio';
|
|
12
12
|
import { INPUT_BACKEND_KEY, InputSet, InputFrameStartScan, attachBrowserInputBackend, inputBackendPlugin, ownedInputBackendPlugin, INPUT_MAP_KEY } from '@forgeax/engine-input';
|
|
13
13
|
import { componentSchema } from '@forgeax/engine-ecs/internal';
|
|
14
14
|
import { animationPayloadsPlugin, animationRuntimePlugin } from '@forgeax/engine-animation';
|
|
15
15
|
import { Transform, scenePlugin } from '@forgeax/engine-scene';
|
|
16
16
|
import { statePlugin } from '@forgeax/engine-state';
|
|
17
|
-
import {
|
|
17
|
+
import { createDebugDraw } from '@forgeax/engine-debug-draw';
|
|
18
18
|
import { createProfiler } from '@forgeax/engine-profiler';
|
|
19
19
|
import { isSerializableValue, createPreviewArtifactManifest, validatePreviewArtifactManifest, createArtifactRef, snapshotStaleError } from '@forgeax/engine-tool-runtime';
|
|
20
20
|
|
|
@@ -96,10 +96,7 @@ function serializeError(error) {
|
|
|
96
96
|
}
|
|
97
97
|
async function installBrowserRemoteBridge(deps) {
|
|
98
98
|
const { world, renderer, assets, rhiCapture, profiler, execution, port } = deps;
|
|
99
|
-
const mod = await import(
|
|
100
|
-
/* @vite-ignore */
|
|
101
|
-
'@forgeax/engine-remote/execute'
|
|
102
|
-
);
|
|
99
|
+
const mod = await import('@forgeax/engine-remote/execute');
|
|
103
100
|
const executeScript = mod.executeScript;
|
|
104
101
|
const importModule = createEcsImportModule((specifier) => {
|
|
105
102
|
if (specifier === "@forgeax/engine-runtime")
|
|
@@ -219,66 +216,11 @@ var init_browser_remote_bridge = __esm({
|
|
|
219
216
|
init_ecs_import();
|
|
220
217
|
}
|
|
221
218
|
});
|
|
222
|
-
function assembleAssetRuntime(registry, contributions) {
|
|
223
|
-
const leases = [];
|
|
224
|
-
const overrides = new Set(contributions.map((contribution) => contribution.kind.kind));
|
|
225
|
-
const defaults = defaultAssetDecoderContributions ?? [];
|
|
226
|
-
const assembledContributions = [
|
|
227
|
-
...defaults.filter((contribution) => !overrides.has(contribution.kind.kind)),
|
|
228
|
-
...contributions
|
|
229
|
-
];
|
|
230
|
-
try {
|
|
231
|
-
const installedKinds = /* @__PURE__ */ new Set();
|
|
232
|
-
for (const contribution of assembledContributions) {
|
|
233
|
-
if (installedKinds.has(contribution.kind.kind)) {
|
|
234
|
-
throw new TypeError(`duplicate decoder kind "${contribution.kind.kind}"`);
|
|
235
|
-
}
|
|
236
|
-
installedKinds.add(contribution.kind.kind);
|
|
237
|
-
leases.push(
|
|
238
|
-
registry.installDecoder(
|
|
239
|
-
contribution.kind,
|
|
240
|
-
contribution.decoder
|
|
241
|
-
)
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
} catch (cause) {
|
|
245
|
-
for (const lease of leases) lease.dispose();
|
|
246
|
-
const failed = assembledContributions[leases.length];
|
|
247
|
-
return err({
|
|
248
|
-
code: "asset-assembly-failed",
|
|
249
|
-
expected: "each owner decoder contribution to install exactly once in the realm registry",
|
|
250
|
-
hint: "remove the conflicting owner contribution and assemble the current realm again",
|
|
251
|
-
detail: { kind: failed?.kind.kind ?? "unknown", cause }
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
let disposed = false;
|
|
255
|
-
return ok({
|
|
256
|
-
registry,
|
|
257
|
-
leases: Object.freeze([...leases]),
|
|
258
|
-
dispose() {
|
|
259
|
-
if (disposed) return;
|
|
260
|
-
disposed = true;
|
|
261
|
-
for (const lease of leases) lease.dispose();
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
219
|
|
|
266
220
|
// src/animation-asset-lookup.ts
|
|
267
221
|
function createAnimationPayloadLookup(source) {
|
|
268
222
|
return (guid) => source?.lookup(guid);
|
|
269
223
|
}
|
|
270
|
-
function syncCameraAspect(world, canvasW, canvasH) {
|
|
271
|
-
if (canvasW <= 0 || canvasH <= 0) return;
|
|
272
|
-
const aspect = canvasW / canvasH;
|
|
273
|
-
const query = world.query({ with: [Camera] }).unwrap();
|
|
274
|
-
for (const row of query) {
|
|
275
|
-
const camera = world.get(row.entity, Camera);
|
|
276
|
-
if (!camera.ok) continue;
|
|
277
|
-
if (camera.value.autoAspect !== true) continue;
|
|
278
|
-
if (camera.value.projection !== CAMERA_PROJECTION_PERSPECTIVE) continue;
|
|
279
|
-
world.set(row.entity, Camera, { aspect });
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
224
|
|
|
283
225
|
// src/errors.ts
|
|
284
226
|
function summarizeCause(cause) {
|
|
@@ -341,10 +283,6 @@ var appErrorPolicy = {
|
|
|
341
283
|
expected: "canvas.isConnected === true at createApp(canvas) entry",
|
|
342
284
|
hint: "append the canvas to the document tree before calling createApp(canvas), or use the assemble entry createApp({ renderer, world }) when the host already manages canvas lifetime"
|
|
343
285
|
},
|
|
344
|
-
"app-invalid-canvas-pixel-ratio": {
|
|
345
|
-
expected: "maxCanvasPixelRatio is finite and greater than 0",
|
|
346
|
-
hint: "omit maxCanvasPixelRatio to keep the device pixel ratio, or pass a finite value > 0 from the Host policy"
|
|
347
|
-
},
|
|
348
286
|
"app-frame-step-invalid": {
|
|
349
287
|
expected: "stepFrame(deltaSeconds) runs only while the App is paused and deltaSeconds is finite and non-negative",
|
|
350
288
|
hint: "pause the App before deterministic stepping and pass an explicit finite delta; resume after the bounded step sequence completes"
|
|
@@ -740,20 +678,17 @@ function createLocalExecutionControl(initial, providers = {}) {
|
|
|
740
678
|
world: providers.world?.() ?? current.world,
|
|
741
679
|
audio: executionAudioReport(providers.audio?.())
|
|
742
680
|
}),
|
|
743
|
-
rebuild: async () =>
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
})
|
|
755
|
-
);
|
|
756
|
-
}
|
|
681
|
+
rebuild: async () => err(
|
|
682
|
+
new AppError({
|
|
683
|
+
code: "app-execution-rebuild-failed",
|
|
684
|
+
expected: APP_EXPECTED["app-execution-rebuild-failed"],
|
|
685
|
+
hint: APP_ERROR_HINTS["app-execution-rebuild-failed"],
|
|
686
|
+
detail: {
|
|
687
|
+
worldIdentity: current.world.identity,
|
|
688
|
+
cause: new Error("This local assembly has no bootstrap module.")
|
|
689
|
+
}
|
|
690
|
+
})
|
|
691
|
+
)
|
|
757
692
|
};
|
|
758
693
|
}
|
|
759
694
|
var ENGINE_WORKER_CAPABILITIES = [
|
|
@@ -828,6 +763,25 @@ function selectExecutionTier(input) {
|
|
|
828
763
|
sharedEvidencePassed: input.sharedEvidencePassed
|
|
829
764
|
});
|
|
830
765
|
}
|
|
766
|
+
function normalizeExecutionBootstrapUrl(bootstrap) {
|
|
767
|
+
const moduleUrl = typeof bootstrap === "string" ? bootstrap : bootstrap.href;
|
|
768
|
+
try {
|
|
769
|
+
return ok(new URL(bootstrap, globalThis.location?.href).href);
|
|
770
|
+
} catch (cause) {
|
|
771
|
+
return err(
|
|
772
|
+
new AppError({
|
|
773
|
+
code: "app-execution-bootstrap-failed",
|
|
774
|
+
expected: APP_EXPECTED["app-execution-bootstrap-failed"],
|
|
775
|
+
hint: APP_ERROR_HINTS["app-execution-bootstrap-failed"],
|
|
776
|
+
detail: {
|
|
777
|
+
phase: "prepare",
|
|
778
|
+
moduleUrl,
|
|
779
|
+
cause: cause instanceof TypeError ? cause : new TypeError(String(cause))
|
|
780
|
+
}
|
|
781
|
+
})
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
831
785
|
|
|
832
786
|
// src/internal/error-fanout.ts
|
|
833
787
|
var ErrorFanoutRegistry = class {
|
|
@@ -977,6 +931,7 @@ async function startEngineWorker(options) {
|
|
|
977
931
|
bootstrapUrl: options.bootstrapUrl,
|
|
978
932
|
...options.bootstrapData === void 0 ? {} : { bootstrapData: options.bootstrapData },
|
|
979
933
|
...options.bootstrapPort === void 0 ? {} : { bootstrapPort: options.bootstrapPort },
|
|
934
|
+
...options.assetCatalog === void 0 ? {} : { assetCatalog: options.assetCatalog },
|
|
980
935
|
...options.shaderManifestUrl !== void 0 ? { shaderManifestUrl: options.shaderManifestUrl } : {},
|
|
981
936
|
...options.time !== void 0 ? { time: options.time } : {},
|
|
982
937
|
tier: options.tier
|
|
@@ -1047,7 +1002,7 @@ var FrameCreditLedger = class {
|
|
|
1047
1002
|
nextFrameId = 1;
|
|
1048
1003
|
inFlight = null;
|
|
1049
1004
|
completed = 0;
|
|
1050
|
-
issue(deltaSeconds, sampleInput, canvasSize) {
|
|
1005
|
+
issue(deltaSeconds, sampleInput, canvasSize = { width: 0, height: 0 }) {
|
|
1051
1006
|
if (this.inFlight !== null) return void 0;
|
|
1052
1007
|
const frameId = this.nextFrameId;
|
|
1053
1008
|
this.nextFrameId += 1;
|
|
@@ -1109,15 +1064,18 @@ function runtimeError(message) {
|
|
|
1109
1064
|
async function createWorkerExecutionApp(options) {
|
|
1110
1065
|
const executionOptions = options.appOptions.execution;
|
|
1111
1066
|
if (executionOptions === void 0) throw new Error("execution options are required");
|
|
1112
|
-
const
|
|
1113
|
-
|
|
1067
|
+
const normalizedBootstrap = normalizeExecutionBootstrapUrl(executionOptions.bootstrap);
|
|
1068
|
+
if (!normalizedBootstrap.ok) return normalizedBootstrap;
|
|
1069
|
+
const bootstrapUrl = normalizedBootstrap.value;
|
|
1114
1070
|
const startupTimeoutMs = executionOptions.startupTimeoutMs ?? 1e4;
|
|
1115
1071
|
const frameTimeoutMs = executionOptions.frameTimeoutMs ?? 2e3;
|
|
1072
|
+
const syncCanvas = options.syncCanvas;
|
|
1116
1073
|
const started = await startEngineWorker({
|
|
1117
1074
|
canvas: options.canvas,
|
|
1118
1075
|
bootstrapUrl,
|
|
1119
1076
|
...executionOptions.bootstrapData === void 0 ? {} : { bootstrapData: executionOptions.bootstrapData },
|
|
1120
1077
|
...executionOptions.bootstrapPort === void 0 ? {} : { bootstrapPort: executionOptions.bootstrapPort },
|
|
1078
|
+
...executionOptions.assetCatalog === void 0 ? {} : { assetCatalog: executionOptions.assetCatalog },
|
|
1121
1079
|
...options.bundler?.shaderManifestUrl !== void 0 ? { shaderManifestUrl: options.bundler.shaderManifestUrl } : {},
|
|
1122
1080
|
...options.appOptions.time !== void 0 ? { time: options.appOptions.time } : {},
|
|
1123
1081
|
timeoutMs: startupTimeoutMs,
|
|
@@ -1453,61 +1411,99 @@ async function createWorkerExecutionApp(options) {
|
|
|
1453
1411
|
return ok(app);
|
|
1454
1412
|
}
|
|
1455
1413
|
|
|
1456
|
-
// src/
|
|
1457
|
-
|
|
1458
|
-
var ASSET_REGISTRY_RESOURCE_KEY = "AssetRegistry";
|
|
1459
|
-
function rendererAssetsPlugin() {
|
|
1414
|
+
// src/renderer-plugin.ts
|
|
1415
|
+
function createRenderFeatureHost(host) {
|
|
1460
1416
|
return {
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1417
|
+
async installFeature(feature) {
|
|
1418
|
+
const installed = await host.installRenderFeature(feature);
|
|
1419
|
+
if (!installed.ok) return installed;
|
|
1420
|
+
let released = false;
|
|
1421
|
+
return {
|
|
1422
|
+
ok: true,
|
|
1423
|
+
value: {
|
|
1424
|
+
release: async () => {
|
|
1425
|
+
if (released) return { ok: true, value: void 0 };
|
|
1426
|
+
released = true;
|
|
1427
|
+
return host.uninstallRenderFeature(feature);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
function rendererPlugin(renderer) {
|
|
1435
|
+
return {
|
|
1436
|
+
name: "renderer",
|
|
1437
|
+
provide: "renderer",
|
|
1464
1438
|
apply(ctx) {
|
|
1465
|
-
|
|
1466
|
-
ctx.provide("assets", ctx.renderer.assets);
|
|
1439
|
+
ctx.provide("renderer", renderer);
|
|
1467
1440
|
}
|
|
1468
1441
|
};
|
|
1469
1442
|
}
|
|
1470
|
-
function
|
|
1443
|
+
function ownedRendererPlugin(renderer) {
|
|
1471
1444
|
return {
|
|
1472
|
-
name: "
|
|
1473
|
-
provide: "
|
|
1445
|
+
name: "renderer",
|
|
1446
|
+
provide: "renderer",
|
|
1474
1447
|
apply(ctx) {
|
|
1475
|
-
ctx.provide("
|
|
1448
|
+
ctx.provide("renderer", renderer);
|
|
1449
|
+
ctx.effect(() => () => renderer.dispose(), "render/renderer");
|
|
1450
|
+
}
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
function renderFeatureHostPlugin(host) {
|
|
1454
|
+
return {
|
|
1455
|
+
name: "render-feature-host",
|
|
1456
|
+
provide: "renderFeatureHost",
|
|
1457
|
+
apply(ctx) {
|
|
1458
|
+
ctx.provide("renderFeatureHost", host);
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
function renderFeaturePlugin(feature) {
|
|
1463
|
+
return {
|
|
1464
|
+
name: `render-feature:${feature.identity}`,
|
|
1465
|
+
inject: ["renderFeatureHost"],
|
|
1466
|
+
async apply(ctx) {
|
|
1467
|
+
if (ctx.renderFeatureHost === void 0) {
|
|
1468
|
+
throw new Error("render-feature host capability is unavailable in this App realm");
|
|
1469
|
+
}
|
|
1470
|
+
const installed = await ctx.renderFeatureHost.installFeature(feature);
|
|
1471
|
+
if (!installed.ok) throw installed.error;
|
|
1476
1472
|
ctx.effect(
|
|
1477
|
-
() => () => {
|
|
1478
|
-
|
|
1479
|
-
|
|
1473
|
+
() => async () => {
|
|
1474
|
+
const removed = await installed.value.release();
|
|
1475
|
+
if (!removed.ok) throw removed.error;
|
|
1480
1476
|
},
|
|
1481
|
-
|
|
1477
|
+
`render-feature/${feature.identity}`
|
|
1482
1478
|
);
|
|
1483
1479
|
}
|
|
1484
1480
|
};
|
|
1485
1481
|
}
|
|
1486
|
-
|
|
1482
|
+
|
|
1483
|
+
// src/internal/assets-world-plugin.ts
|
|
1484
|
+
var ASSET_REGISTRY_RESOURCE_KEY = "AssetRegistry";
|
|
1485
|
+
function rendererAssetsPlugin(assets) {
|
|
1487
1486
|
return {
|
|
1488
|
-
name: "assets
|
|
1489
|
-
inject: ["
|
|
1487
|
+
name: "renderer-assets",
|
|
1488
|
+
inject: ["renderer"],
|
|
1489
|
+
provide: "assets",
|
|
1490
1490
|
apply(ctx) {
|
|
1491
|
-
ctx.
|
|
1492
|
-
ctx.world.insertResource(RENDER_ASSET_PORT_RESOURCE_KEY, ctx.assets);
|
|
1493
|
-
return () => {
|
|
1494
|
-
ctx.world.removeResource(RENDER_ASSET_PORT_RESOURCE_KEY);
|
|
1495
|
-
};
|
|
1496
|
-
}, "assets/world-render-projection");
|
|
1491
|
+
if (assets !== void 0) ctx.provide("assets", assets);
|
|
1497
1492
|
}
|
|
1498
1493
|
};
|
|
1499
1494
|
}
|
|
1500
|
-
function
|
|
1495
|
+
function assetsWorldPlugin() {
|
|
1501
1496
|
return {
|
|
1502
|
-
name: "
|
|
1503
|
-
inject: ["world", "
|
|
1497
|
+
name: "assets-world",
|
|
1498
|
+
inject: ["world", "assets"],
|
|
1504
1499
|
apply(ctx) {
|
|
1500
|
+
if (ctx.assets === void 0) return;
|
|
1505
1501
|
ctx.effect(() => {
|
|
1506
|
-
ctx.world.insertResource(ASSET_REGISTRY_RESOURCE_KEY, ctx.
|
|
1502
|
+
ctx.world.insertResource(ASSET_REGISTRY_RESOURCE_KEY, ctx.assets);
|
|
1507
1503
|
return () => {
|
|
1508
1504
|
ctx.world.removeResource(ASSET_REGISTRY_RESOURCE_KEY);
|
|
1509
1505
|
};
|
|
1510
|
-
}, "assets/world-
|
|
1506
|
+
}, "assets/world-resource");
|
|
1511
1507
|
}
|
|
1512
1508
|
};
|
|
1513
1509
|
}
|
|
@@ -1516,8 +1512,7 @@ function assetRegistryWorldPlugin() {
|
|
|
1516
1512
|
function assembledEngineProfile(options) {
|
|
1517
1513
|
return [
|
|
1518
1514
|
rendererPlugin(options.renderer),
|
|
1519
|
-
rendererAssetsPlugin(),
|
|
1520
|
-
...options.assetAssembly === void 0 ? [] : [assetRegistryPlugin(options.assetAssembly), assetRegistryWorldPlugin()],
|
|
1515
|
+
rendererAssetsPlugin(options.assets),
|
|
1521
1516
|
assetsWorldPlugin(),
|
|
1522
1517
|
...options.extensions ?? []
|
|
1523
1518
|
];
|
|
@@ -1680,7 +1675,6 @@ function resolveCaf(opts) {
|
|
|
1680
1675
|
}
|
|
1681
1676
|
function createFrameLoop(opts) {
|
|
1682
1677
|
const { world, renderer } = opts;
|
|
1683
|
-
const primaryDrawWorlds = [world];
|
|
1684
1678
|
const phaseCatalogRegistration = opts.profiler?.registerPhaseCatalog("app", APP_PHASE_CATALOG);
|
|
1685
1679
|
let releasePhaseCatalog = phaseCatalogRegistration?.ok === true ? phaseCatalogRegistration.value : void 0;
|
|
1686
1680
|
let drawSource = opts.drawSource;
|
|
@@ -1692,53 +1686,50 @@ function createFrameLoop(opts) {
|
|
|
1692
1686
|
let pendingFrameId = 0;
|
|
1693
1687
|
let profilerFrameId = 0;
|
|
1694
1688
|
let profilerCaptureId;
|
|
1695
|
-
|
|
1696
|
-
let activeInjectedWorlds;
|
|
1697
|
-
let nextInjectedWorlds;
|
|
1689
|
+
const leases = /* @__PURE__ */ new Map();
|
|
1698
1690
|
function attachPrimary(fireError) {
|
|
1699
|
-
if (
|
|
1691
|
+
if (leases.has(world)) return;
|
|
1700
1692
|
try {
|
|
1701
|
-
const result = renderer.
|
|
1702
|
-
|
|
1703
|
-
|
|
1693
|
+
const result = renderer.attach(world);
|
|
1694
|
+
if (result.ok) leases.set(world, result.value);
|
|
1695
|
+
else fireError(result.error);
|
|
1704
1696
|
} catch (cause) {
|
|
1705
1697
|
fireError(makeWorldUpdateError(cause));
|
|
1706
1698
|
}
|
|
1707
1699
|
}
|
|
1708
1700
|
function syncInjectedAttachments(worlds, fireError) {
|
|
1709
1701
|
if (worlds === void 0) {
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1702
|
+
for (const [attached, lease] of leases) {
|
|
1703
|
+
if (attached !== world) {
|
|
1704
|
+
lease.dispose();
|
|
1705
|
+
leases.delete(attached);
|
|
1706
|
+
}
|
|
1713
1707
|
}
|
|
1714
1708
|
return void 0;
|
|
1715
1709
|
}
|
|
1716
|
-
const next =
|
|
1717
|
-
nextInjectedWorlds = next;
|
|
1718
|
-
next.clear();
|
|
1719
|
-
const active = activeInjectedWorlds;
|
|
1710
|
+
const next = /* @__PURE__ */ new Set();
|
|
1720
1711
|
for (const candidate of worlds) {
|
|
1721
1712
|
if (candidate === world || next.has(candidate)) continue;
|
|
1722
|
-
if (
|
|
1713
|
+
if (leases.has(candidate)) {
|
|
1723
1714
|
next.add(candidate);
|
|
1724
1715
|
continue;
|
|
1725
1716
|
}
|
|
1726
1717
|
try {
|
|
1727
|
-
const result = renderer.
|
|
1728
|
-
if (result.ok)
|
|
1729
|
-
|
|
1718
|
+
const result = renderer.attach(candidate);
|
|
1719
|
+
if (result.ok) {
|
|
1720
|
+
leases.set(candidate, result.value);
|
|
1721
|
+
next.add(candidate);
|
|
1722
|
+
} else fireError?.(result.error);
|
|
1730
1723
|
} catch (cause) {
|
|
1731
1724
|
fireError?.(makeWorldUpdateError(cause));
|
|
1732
1725
|
}
|
|
1733
1726
|
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1727
|
+
for (const [attached, lease] of leases) {
|
|
1728
|
+
if (attached !== world && !next.has(attached)) {
|
|
1729
|
+
lease.dispose();
|
|
1730
|
+
leases.delete(attached);
|
|
1737
1731
|
}
|
|
1738
|
-
active.clear();
|
|
1739
1732
|
}
|
|
1740
|
-
activeInjectedWorlds = next;
|
|
1741
|
-
nextInjectedWorlds = active;
|
|
1742
1733
|
return next;
|
|
1743
1734
|
}
|
|
1744
1735
|
function releaseInjectedAttachments() {
|
|
@@ -1746,9 +1737,11 @@ function createFrameLoop(opts) {
|
|
|
1746
1737
|
}
|
|
1747
1738
|
function releaseAttachments() {
|
|
1748
1739
|
releaseInjectedAttachments();
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1740
|
+
const lease = leases.get(world);
|
|
1741
|
+
if (lease !== void 0) {
|
|
1742
|
+
lease.dispose();
|
|
1743
|
+
leases.delete(world);
|
|
1744
|
+
}
|
|
1752
1745
|
}
|
|
1753
1746
|
function runProfiledPhase(session, phase, action) {
|
|
1754
1747
|
const opened = beginPhase(session, phase);
|
|
@@ -1799,7 +1792,7 @@ function createFrameLoop(opts) {
|
|
|
1799
1792
|
});
|
|
1800
1793
|
const attachedInjectedWorlds = syncInjectedAttachments(injected?.worlds, reportError);
|
|
1801
1794
|
const updatedWorlds = injected === void 0 ? void 0 : /* @__PURE__ */ new Set();
|
|
1802
|
-
if (updatedWorlds !== void 0 && primaryUpdated &&
|
|
1795
|
+
if (updatedWorlds !== void 0 && primaryUpdated && leases.has(world)) {
|
|
1803
1796
|
updatedWorlds.add(world);
|
|
1804
1797
|
}
|
|
1805
1798
|
runProfiledPhase(session, "world-update-injected", () => {
|
|
@@ -1816,27 +1809,34 @@ function createFrameLoop(opts) {
|
|
|
1816
1809
|
});
|
|
1817
1810
|
runProfiledPhase(session, "renderer-draw", () => {
|
|
1818
1811
|
try {
|
|
1819
|
-
const profileOptions = profileFrame === void 0 ? {} : { profileFrame };
|
|
1820
1812
|
let drawResult;
|
|
1821
1813
|
if (injected === void 0) {
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1814
|
+
const primaryLease = leases.get(world);
|
|
1815
|
+
if (!primaryUpdated || primaryLease === void 0) return;
|
|
1816
|
+
drawResult = renderer.draw({
|
|
1817
|
+
leases: [primaryLease],
|
|
1818
|
+
camera: { lease: primaryLease },
|
|
1819
|
+
environment: { lease: primaryLease },
|
|
1820
|
+
...profileFrame === void 0 ? {} : { profileFrame }
|
|
1827
1821
|
});
|
|
1828
1822
|
} else {
|
|
1829
1823
|
if (updatedWorlds === void 0) return;
|
|
1830
|
-
const
|
|
1824
|
+
const readyEntries = injected.worlds.filter((candidate) => updatedWorlds.has(candidate)).map((candidate) => ({ candidate, lease: leases.get(candidate) })).filter(
|
|
1825
|
+
(entry) => entry.lease !== void 0
|
|
1826
|
+
);
|
|
1827
|
+
const readyLeases = readyEntries.map((entry) => entry.lease);
|
|
1831
1828
|
const cameraWorld = injected.worlds[injected.cameraOwner];
|
|
1832
|
-
const
|
|
1833
|
-
|
|
1834
|
-
const
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1829
|
+
const environmentWorld = injected.worlds[injected.resourceOwner];
|
|
1830
|
+
if (cameraWorld === void 0 || environmentWorld === void 0) return;
|
|
1831
|
+
const cameraLease = leases.get(cameraWorld);
|
|
1832
|
+
const environmentLease = leases.get(environmentWorld);
|
|
1833
|
+
if (readyLeases.length === 0 || cameraLease === void 0 || environmentLease === void 0)
|
|
1834
|
+
return;
|
|
1835
|
+
drawResult = renderer.draw({
|
|
1836
|
+
leases: readyLeases,
|
|
1837
|
+
camera: { lease: cameraLease },
|
|
1838
|
+
environment: { lease: environmentLease },
|
|
1839
|
+
...profileFrame === void 0 ? {} : { profileFrame }
|
|
1840
1840
|
});
|
|
1841
1841
|
}
|
|
1842
1842
|
if (drawResult !== void 0) {
|
|
@@ -1851,14 +1851,14 @@ function createFrameLoop(opts) {
|
|
|
1851
1851
|
});
|
|
1852
1852
|
});
|
|
1853
1853
|
endFrame(session);
|
|
1854
|
+
try {
|
|
1855
|
+
opts.debugRhi?.onFrameEnd();
|
|
1856
|
+
} catch {
|
|
1857
|
+
}
|
|
1854
1858
|
return frameError === void 0 ? ok(void 0) : err(frameError);
|
|
1855
1859
|
}
|
|
1856
1860
|
function tick() {
|
|
1857
1861
|
if (state !== "running") return;
|
|
1858
|
-
if (renderer.health?.().reason === "device-lost") {
|
|
1859
|
-
pendingFrameId = raf(tick);
|
|
1860
|
-
return;
|
|
1861
|
-
}
|
|
1862
1862
|
const timestamp = now();
|
|
1863
1863
|
const deltaSeconds = (timestamp - lastTimestamp) / 1e3;
|
|
1864
1864
|
lastTimestamp = timestamp;
|
|
@@ -2066,17 +2066,53 @@ function inputPlugin() {
|
|
|
2066
2066
|
};
|
|
2067
2067
|
}
|
|
2068
2068
|
|
|
2069
|
+
// ../render/src/record/render-context.ts
|
|
2070
|
+
function selectSwapChainFormat(storageBufferCapable) {
|
|
2071
|
+
if (!storageBufferCapable) return { storage: "rgba8unorm", view: "rgba8unorm-srgb" };
|
|
2072
|
+
const nav = globalThis.navigator;
|
|
2073
|
+
const gpu = nav?.gpu;
|
|
2074
|
+
const getPreferred = gpu?.getPreferredCanvasFormat;
|
|
2075
|
+
if (gpu !== void 0 && typeof getPreferred === "function") {
|
|
2076
|
+
const storage = getPreferred.call(gpu);
|
|
2077
|
+
const view = storage === "rgba8unorm" ? "rgba8unorm-srgb" : storage === "bgra8unorm" ? "bgra8unorm-srgb" : storage;
|
|
2078
|
+
return { storage, view };
|
|
2079
|
+
}
|
|
2080
|
+
return {
|
|
2081
|
+
storage: "rgba8unorm",
|
|
2082
|
+
view: "rgba8unorm-srgb",
|
|
2083
|
+
fallbackReason: "preferred-canvas-format-missing"
|
|
2084
|
+
};
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
// src/internal/debug-draw.ts
|
|
2088
|
+
async function createDebugDrawOnReady(context, format) {
|
|
2089
|
+
const ready = await context.initialization;
|
|
2090
|
+
if (!ready.ok) throw ready.error;
|
|
2091
|
+
const resolvedFormat = selectSwapChainFormat(context.device.caps.storageBuffer).view;
|
|
2092
|
+
const result = await createDebugDraw({
|
|
2093
|
+
device: context.device,
|
|
2094
|
+
queue: context.device.queue,
|
|
2095
|
+
createShaderModule: context._internal_createShaderModule,
|
|
2096
|
+
format: resolvedFormat
|
|
2097
|
+
});
|
|
2098
|
+
if (!result.ok) throw result.error;
|
|
2099
|
+
context._internal_setRenderOverlay(result.value);
|
|
2100
|
+
return result.value;
|
|
2101
|
+
}
|
|
2102
|
+
function releaseDebugDraw(context, debugDraw) {
|
|
2103
|
+
context._internal_setRenderOverlay(void 0);
|
|
2104
|
+
debugDraw.destroy();
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2069
2107
|
// src/internal/main-engine-profile.ts
|
|
2070
|
-
function debugDrawPlugin(onReady) {
|
|
2108
|
+
function debugDrawPlugin(context, onReady) {
|
|
2071
2109
|
return {
|
|
2072
2110
|
name: "debug-draw",
|
|
2073
|
-
inject: ["renderer"],
|
|
2074
2111
|
async apply(ctx) {
|
|
2075
|
-
if (ctx.renderer === void 0) throw new Error("debug draw requires the renderer service");
|
|
2076
2112
|
try {
|
|
2077
|
-
const debugDraw = await createDebugDrawOnReady(
|
|
2113
|
+
const debugDraw = await createDebugDrawOnReady(context);
|
|
2078
2114
|
onReady(debugDraw);
|
|
2079
|
-
ctx.effect(() => () => releaseDebugDraw(debugDraw), "render/debug-draw");
|
|
2115
|
+
ctx.effect(() => () => releaseDebugDraw(context, debugDraw), "render/debug-draw");
|
|
2080
2116
|
} catch {
|
|
2081
2117
|
}
|
|
2082
2118
|
}
|
|
@@ -2086,8 +2122,8 @@ function mainEngineProfile(options) {
|
|
|
2086
2122
|
return [
|
|
2087
2123
|
ownedRendererPlugin(options.renderer),
|
|
2088
2124
|
renderComponentsPlugin(),
|
|
2089
|
-
|
|
2090
|
-
|
|
2125
|
+
...options.rendererFeatureHost === void 0 ? [] : [renderFeatureHostPlugin(options.rendererFeatureHost)],
|
|
2126
|
+
rendererAssetsPlugin(options.assets),
|
|
2091
2127
|
assetsWorldPlugin(),
|
|
2092
2128
|
...options.input === void 0 ? [] : [
|
|
2093
2129
|
options.inputDispose === void 0 ? inputBackendPlugin(options.input) : ownedInputBackendPlugin(options.input, options.inputDispose)
|
|
@@ -2096,7 +2132,7 @@ function mainEngineProfile(options) {
|
|
|
2096
2132
|
animationPayloadsPlugin(options.animationPayloads),
|
|
2097
2133
|
animationRuntimePlugin(),
|
|
2098
2134
|
statePlugin(),
|
|
2099
|
-
...options.onDebugDrawReady === void 0 ? [] : [debugDrawPlugin(options.onDebugDrawReady)],
|
|
2135
|
+
...options.onDebugDrawReady === void 0 || options.rendererDebugDrawHost === void 0 ? [] : [debugDrawPlugin(options.rendererDebugDrawHost, options.onDebugDrawReady)],
|
|
2100
2136
|
...options.input === void 0 ? [] : [inputPlugin()],
|
|
2101
2137
|
...options.inputMap === void 0 ? [] : [inputMapPlugin(options.inputMap)],
|
|
2102
2138
|
...options.extensions ?? []
|
|
@@ -2104,8 +2140,7 @@ function mainEngineProfile(options) {
|
|
|
2104
2140
|
}
|
|
2105
2141
|
|
|
2106
2142
|
// src/internal/remote-serve-flag.ts
|
|
2107
|
-
function resolveRemoteServeFlag(isDev, processEnv
|
|
2108
|
-
if (isBrowser) return false;
|
|
2143
|
+
function resolveRemoteServeFlag(isDev, processEnv) {
|
|
2109
2144
|
if (isDev === true) return true;
|
|
2110
2145
|
if (processEnv?.FORGEAX_ENGINE_REMOTE_SERVE === "1") return true;
|
|
2111
2146
|
return false;
|
|
@@ -2292,38 +2327,10 @@ function resolveRhiDebugFlag(importMetaEnv, processEnv) {
|
|
|
2292
2327
|
}
|
|
2293
2328
|
|
|
2294
2329
|
// src/create-app.ts
|
|
2295
|
-
var DEFAULT_ASSET_CATALOG_PATH = "pack-index.json";
|
|
2296
|
-
function defaultAssetCatalogUrl() {
|
|
2297
|
-
const base = typeof document !== "undefined" ? document.baseURI : globalThis.location?.href;
|
|
2298
|
-
return base === void 0 ? DEFAULT_ASSET_CATALOG_PATH : new URL(DEFAULT_ASSET_CATALOG_PATH, base).href;
|
|
2299
|
-
}
|
|
2300
|
-
function assembleAppAssetRuntime(catalog, contributions) {
|
|
2301
|
-
const registry = createAssetRegistry({
|
|
2302
|
-
catalog: catalog ?? createCatalogSource({ url: defaultAssetCatalogUrl() })
|
|
2303
|
-
});
|
|
2304
|
-
const assembled = assembleAssetRuntime(registry, contributions ?? []);
|
|
2305
|
-
if (!assembled.ok) registry.dispose();
|
|
2306
|
-
return assembled;
|
|
2307
|
-
}
|
|
2308
2330
|
function makeAppError2(code, expected, hint, detail) {
|
|
2309
2331
|
return new AppError({ code, expected, hint, detail });
|
|
2310
2332
|
}
|
|
2311
|
-
function
|
|
2312
|
-
const moduleUrl = typeof bootstrap === "string" ? bootstrap : bootstrap.href;
|
|
2313
|
-
try {
|
|
2314
|
-
return ok(new URL(bootstrap, globalThis.location?.href).href);
|
|
2315
|
-
} catch (cause) {
|
|
2316
|
-
return err(
|
|
2317
|
-
makeAppError2(
|
|
2318
|
-
"app-execution-bootstrap-failed",
|
|
2319
|
-
APP_EXPECTED["app-execution-bootstrap-failed"],
|
|
2320
|
-
APP_ERROR_HINTS["app-execution-bootstrap-failed"],
|
|
2321
|
-
{ phase: "prepare", moduleUrl, cause }
|
|
2322
|
-
)
|
|
2323
|
-
);
|
|
2324
|
-
}
|
|
2325
|
-
}
|
|
2326
|
-
function canvasAspectPlugin(canvas, maxCanvasPixelRatio) {
|
|
2333
|
+
function canvasAspectPlugin(canvas) {
|
|
2327
2334
|
return {
|
|
2328
2335
|
name: "canvas-aspect",
|
|
2329
2336
|
inject: ["world"],
|
|
@@ -2333,7 +2340,7 @@ function canvasAspectPlugin(canvas, maxCanvasPixelRatio) {
|
|
|
2333
2340
|
name: "app-sync-camera-aspect",
|
|
2334
2341
|
queries: [],
|
|
2335
2342
|
fn: () => {
|
|
2336
|
-
syncCanvasDrawingBuffer(canvas
|
|
2343
|
+
syncCanvasDrawingBuffer(canvas);
|
|
2337
2344
|
syncCameraAspect(ctx.world, canvas.width, canvas.height);
|
|
2338
2345
|
}
|
|
2339
2346
|
};
|
|
@@ -2358,17 +2365,6 @@ function createApp(arg, opts, bundler) {
|
|
|
2358
2365
|
return createAppFromAssemble(arg);
|
|
2359
2366
|
}
|
|
2360
2367
|
async function createAppFromCanvas(canvas, opts, bundler) {
|
|
2361
|
-
const maxCanvasPixelRatio = opts?.maxCanvasPixelRatio;
|
|
2362
|
-
if (maxCanvasPixelRatio !== void 0 && (!Number.isFinite(maxCanvasPixelRatio) || maxCanvasPixelRatio <= 0)) {
|
|
2363
|
-
return err(
|
|
2364
|
-
makeAppError2(
|
|
2365
|
-
"app-invalid-canvas-pixel-ratio",
|
|
2366
|
-
APP_EXPECTED["app-invalid-canvas-pixel-ratio"],
|
|
2367
|
-
APP_ERROR_HINTS["app-invalid-canvas-pixel-ratio"],
|
|
2368
|
-
{ value: maxCanvasPixelRatio }
|
|
2369
|
-
)
|
|
2370
|
-
);
|
|
2371
|
-
}
|
|
2372
2368
|
if (!canvas.isConnected) {
|
|
2373
2369
|
return err(
|
|
2374
2370
|
makeAppError2(
|
|
@@ -2379,22 +2375,18 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2379
2375
|
)
|
|
2380
2376
|
);
|
|
2381
2377
|
}
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
if (
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
if (opts?.execution !== void 0 && normalizedExecutionBootstrap?.ok === true) {
|
|
2378
|
+
syncCanvasDrawingBuffer(canvas);
|
|
2379
|
+
let executionBootstrapUrl;
|
|
2380
|
+
if (opts?.execution !== void 0) {
|
|
2381
|
+
const normalizedBootstrap = normalizeExecutionBootstrapUrl(opts.execution.bootstrap);
|
|
2382
|
+
if (!normalizedBootstrap.ok) return err(normalizedBootstrap.error);
|
|
2383
|
+
executionBootstrapUrl = normalizedBootstrap.value;
|
|
2389
2384
|
const realmBoundOption = [
|
|
2390
2385
|
["features", opts.features],
|
|
2391
2386
|
["plugins", opts.plugins],
|
|
2392
2387
|
["rhi", opts.rhi],
|
|
2393
|
-
["
|
|
2388
|
+
["rhiInstrumentation", opts.rhiInstrumentation],
|
|
2394
2389
|
["drawSource", opts.drawSource],
|
|
2395
|
-
["membershipTiming", opts.membershipTiming],
|
|
2396
|
-
["assetCatalog", opts.assetCatalog],
|
|
2397
|
-
["assetDecoders", opts.assetDecoders],
|
|
2398
2390
|
["bundler.importTransport", bundler?.importTransport]
|
|
2399
2391
|
].find(([, value]) => value !== void 0)?.[0];
|
|
2400
2392
|
if (realmBoundOption !== void 0) {
|
|
@@ -2405,7 +2397,7 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2405
2397
|
APP_ERROR_HINTS["app-execution-bootstrap-failed"],
|
|
2406
2398
|
{
|
|
2407
2399
|
phase: "prepare",
|
|
2408
|
-
moduleUrl:
|
|
2400
|
+
moduleUrl: executionBootstrapUrl,
|
|
2409
2401
|
cause: new TypeError(
|
|
2410
2402
|
`${realmBoundOption} must be constructed by the execution bootstrap module`
|
|
2411
2403
|
)
|
|
@@ -2416,11 +2408,10 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2416
2408
|
}
|
|
2417
2409
|
let executionContext;
|
|
2418
2410
|
let preparedExecutionBootstrap;
|
|
2419
|
-
if (opts?.execution !== void 0
|
|
2420
|
-
const executionOptions2 = opts.execution;
|
|
2411
|
+
if (opts?.execution !== void 0) {
|
|
2421
2412
|
const capabilities = await probeExecutionCapabilities(canvas);
|
|
2422
2413
|
const selected = selectExecutionTier({
|
|
2423
|
-
requestedTier:
|
|
2414
|
+
requestedTier: opts.execution.tier ?? "auto",
|
|
2424
2415
|
capabilities,
|
|
2425
2416
|
sharedEvidencePassed: true
|
|
2426
2417
|
});
|
|
@@ -2430,15 +2421,18 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2430
2421
|
return createWorkerExecutionApp({
|
|
2431
2422
|
canvas,
|
|
2432
2423
|
appOptions: opts,
|
|
2433
|
-
syncCanvas: () => measureCanvasDrawingBuffer(canvas
|
|
2424
|
+
syncCanvas: () => measureCanvasDrawingBuffer(canvas),
|
|
2434
2425
|
...bundler !== void 0 ? { bundler } : {},
|
|
2435
2426
|
capabilities,
|
|
2436
2427
|
selection: selected.value
|
|
2437
2428
|
});
|
|
2438
2429
|
}
|
|
2430
|
+
if (executionBootstrapUrl === void 0) {
|
|
2431
|
+
throw new Error("execution bootstrap URL was not normalized");
|
|
2432
|
+
}
|
|
2439
2433
|
const prepared = await prepareBootstrapEntry(
|
|
2440
|
-
|
|
2441
|
-
|
|
2434
|
+
executionBootstrapUrl,
|
|
2435
|
+
opts.execution.bootstrapData
|
|
2442
2436
|
);
|
|
2443
2437
|
if (!prepared.ok) return err(prepared.error);
|
|
2444
2438
|
preparedExecutionBootstrap = prepared.value;
|
|
@@ -2447,24 +2441,19 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2447
2441
|
if (opts?.rhi !== void 0) {
|
|
2448
2442
|
Object.assign(rendererOpts, { rhi: opts.rhi });
|
|
2449
2443
|
}
|
|
2450
|
-
if (opts?.rhiInstrumentation !== void 0) {
|
|
2451
|
-
Object.assign(rendererOpts, { rhiInstrumentation: opts.rhiInstrumentation });
|
|
2452
|
-
}
|
|
2453
|
-
if (opts?.rawDeviceForContextConfigure !== void 0) {
|
|
2454
|
-
Object.assign(rendererOpts, {
|
|
2455
|
-
rawDeviceForContextConfigure: opts.rawDeviceForContextConfigure
|
|
2456
|
-
});
|
|
2457
|
-
}
|
|
2458
2444
|
if (opts?.profiler !== void 0) {
|
|
2459
2445
|
Object.assign(rendererOpts, { profiler: opts.profiler });
|
|
2460
2446
|
}
|
|
2461
|
-
if (opts?.membershipTiming !== void 0) {
|
|
2462
|
-
Object.assign(rendererOpts, { membershipTiming: opts.membershipTiming });
|
|
2463
|
-
}
|
|
2464
2447
|
const rendererFeatures = preparedExecutionBootstrap?.features ?? opts?.features;
|
|
2465
2448
|
if (rendererFeatures !== void 0) {
|
|
2466
2449
|
Object.assign(rendererOpts, { features: rendererFeatures });
|
|
2467
2450
|
}
|
|
2451
|
+
if (opts?.standardProfile !== void 0) {
|
|
2452
|
+
Object.assign(rendererOpts, { standardProfile: opts.standardProfile });
|
|
2453
|
+
}
|
|
2454
|
+
if (opts?.rhiInstrumentation !== void 0) {
|
|
2455
|
+
Object.assign(rendererOpts, { rhiInstrumentation: opts.rhiInstrumentation });
|
|
2456
|
+
}
|
|
2468
2457
|
let rhiAttachment;
|
|
2469
2458
|
let rhiCapture;
|
|
2470
2459
|
let rhiDebugGlobal;
|
|
@@ -2482,61 +2471,54 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2482
2471
|
const rhiDebugFlag = resolveRhiDebugFlag(importMetaEnv, processEnv);
|
|
2483
2472
|
const nav = typeof globalThis !== "undefined" ? globalThis.navigator : void 0;
|
|
2484
2473
|
const hasWebGPU = nav !== void 0 && "gpu" in nav && nav.gpu !== void 0;
|
|
2485
|
-
if (
|
|
2486
|
-
const
|
|
2487
|
-
if (!hasWebGPU && "ensureReady" in
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
'@forgeax/engine-rhi-debug'
|
|
2492
|
-
);
|
|
2474
|
+
if ((browserBuildRhiDebugFlag === void 0 || browserBuildRhiDebugFlag === "1") && rhiDebugFlag === "1") {
|
|
2475
|
+
const realBackend = hasWebGPU ? await import('@forgeax/engine-rhi-webgpu') : await import('@forgeax/engine-rhi-wgpu');
|
|
2476
|
+
if (!hasWebGPU && "ensureReady" in realBackend) {
|
|
2477
|
+
await realBackend.ensureReady();
|
|
2478
|
+
}
|
|
2479
|
+
const pack = loadRhiPack(realBackend);
|
|
2493
2480
|
if (pack.createShaderModule === void 0) {
|
|
2494
|
-
throw new Error("RHI
|
|
2481
|
+
throw new Error("RHI-debug requires a backend createShaderModule capability");
|
|
2495
2482
|
}
|
|
2496
|
-
const
|
|
2497
|
-
const attached = debugModule.attachRecorder({
|
|
2483
|
+
const attached = attachRecorder({
|
|
2498
2484
|
rhi: pack.rhi,
|
|
2499
|
-
createShaderModule
|
|
2485
|
+
createShaderModule: pack.createShaderModule
|
|
2500
2486
|
});
|
|
2501
2487
|
if (!attached.ok) throw new Error(attached.error.hint);
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
const capture =
|
|
2505
|
-
|
|
2488
|
+
rhiAttachment = attached.value;
|
|
2489
|
+
rhiCapture = createRhiCapture(attached.value);
|
|
2490
|
+
const capture = rhiCapture;
|
|
2491
|
+
rhiDebugGlobal = { captureFrame: (options) => capture.captureFrame(options) };
|
|
2506
2492
|
Object.assign(rendererOpts, {
|
|
2507
|
-
rhi:
|
|
2508
|
-
rhiInstrumentation: createRhiInstrumentation(
|
|
2493
|
+
rhi: attached.value.backend.rhi,
|
|
2494
|
+
rhiInstrumentation: createRhiInstrumentation(attached.value)
|
|
2509
2495
|
});
|
|
2510
|
-
rhiDebugGlobal = {
|
|
2511
|
-
captureFrame: (options) => capture.captureFrame(options)
|
|
2512
|
-
};
|
|
2513
2496
|
globalThis.__forgeax = rhiDebugGlobal;
|
|
2514
2497
|
}
|
|
2515
|
-
const assetAssemblyResult = assembleAppAssetRuntime(opts?.assetCatalog, opts?.assetDecoders);
|
|
2516
|
-
if (!assetAssemblyResult.ok) {
|
|
2517
|
-
cleanupRhiDebugHost();
|
|
2518
|
-
return err(assetAssemblyResult.error);
|
|
2519
|
-
}
|
|
2520
|
-
const assetAssembly = assetAssemblyResult.value;
|
|
2521
2498
|
let renderer;
|
|
2499
|
+
let rendererDebugDrawHost;
|
|
2500
|
+
let rendererFeatureHost;
|
|
2501
|
+
let assets;
|
|
2522
2502
|
try {
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2503
|
+
const constructed = await constructRuntimeRendererHost(canvas, rendererOpts, bundler);
|
|
2504
|
+
if (!constructed.ok) throw constructed.error;
|
|
2505
|
+
renderer = constructed.value.renderer;
|
|
2506
|
+
rendererDebugDrawHost = constructed.value.debugDrawHost;
|
|
2507
|
+
rendererFeatureHost = createRenderFeatureHost(constructed.value.featureHost);
|
|
2508
|
+
assets = constructed.value.assets;
|
|
2527
2509
|
} catch (e) {
|
|
2528
2510
|
cleanupRhiDebugHost();
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2511
|
+
if (e instanceof EngineEnvironmentError) return err(e);
|
|
2512
|
+
const detail = e instanceof Error ? e : new Error(String(e));
|
|
2513
|
+
return err(
|
|
2514
|
+
new EngineEnvironmentError("renderer construction failed", {
|
|
2515
|
+
webgpuError: detail
|
|
2516
|
+
})
|
|
2517
|
+
);
|
|
2535
2518
|
}
|
|
2536
2519
|
const shouldStartRemote = resolveRemoteServeFlag(
|
|
2537
2520
|
typeof import.meta !== "undefined" ? import.meta.env?.DEV : void 0,
|
|
2538
|
-
globalThis.process?.env
|
|
2539
|
-
typeof window !== "undefined"
|
|
2521
|
+
globalThis.process?.env
|
|
2540
2522
|
);
|
|
2541
2523
|
let debugDraw;
|
|
2542
2524
|
const world = new World(opts?.time !== void 0 ? { time: opts.time } : {});
|
|
@@ -2560,8 +2542,10 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2560
2542
|
world,
|
|
2561
2543
|
mainEngineProfile({
|
|
2562
2544
|
renderer,
|
|
2563
|
-
|
|
2564
|
-
|
|
2545
|
+
rendererDebugDrawHost,
|
|
2546
|
+
rendererFeatureHost,
|
|
2547
|
+
assets,
|
|
2548
|
+
animationPayloads: createAnimationPayloadLookup(assets),
|
|
2565
2549
|
...inputBackend === void 0 ? {} : { input: inputBackend },
|
|
2566
2550
|
...inputHandle === void 0 ? {} : { inputDispose: inputHandle.cleanup },
|
|
2567
2551
|
...opts?.inputMap === void 0 ? {} : { inputMap: opts.inputMap },
|
|
@@ -2571,14 +2555,12 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2571
2555
|
extensions: [
|
|
2572
2556
|
rhiDebugHostPlugin(cleanupRhiDebugHost),
|
|
2573
2557
|
...userPlugins,
|
|
2574
|
-
canvasAspectPlugin(canvas
|
|
2558
|
+
canvasAspectPlugin(canvas)
|
|
2575
2559
|
]
|
|
2576
2560
|
})
|
|
2577
2561
|
);
|
|
2578
2562
|
} catch (cause) {
|
|
2579
2563
|
cleanupRhiDebugHost();
|
|
2580
|
-
assetAssembly.dispose();
|
|
2581
|
-
assetAssembly.registry.dispose();
|
|
2582
2564
|
return err(
|
|
2583
2565
|
makeAppError2(
|
|
2584
2566
|
"app-plugin-activation-failed",
|
|
@@ -2626,18 +2608,11 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2626
2608
|
})
|
|
2627
2609
|
}
|
|
2628
2610
|
);
|
|
2629
|
-
const remoteHandle = shouldStartRemote ? await startRemoteServer(
|
|
2630
|
-
world,
|
|
2631
|
-
renderer,
|
|
2632
|
-
assetAssembly.registry,
|
|
2633
|
-
rhiCapture,
|
|
2634
|
-
opts?.profiler,
|
|
2635
|
-
executionControl
|
|
2636
|
-
) : void 0;
|
|
2611
|
+
const remoteHandle = shouldStartRemote ? await startRemoteServer(world, renderer, assets, rhiCapture, opts?.profiler, executionControl) : void 0;
|
|
2637
2612
|
if (remoteHandle !== void 0) await pluginContext.plugin(remoteServerPlugin(remoteHandle));
|
|
2638
2613
|
const buildArgs = {
|
|
2639
2614
|
renderer,
|
|
2640
|
-
assets
|
|
2615
|
+
assets,
|
|
2641
2616
|
world,
|
|
2642
2617
|
pluginContext,
|
|
2643
2618
|
executionControl,
|
|
@@ -2663,10 +2638,7 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2663
2638
|
Object.assign(buildArgs, { profiler: opts.profiler });
|
|
2664
2639
|
}
|
|
2665
2640
|
if (rhiCapture !== void 0) {
|
|
2666
|
-
Object.assign(buildArgs, {
|
|
2667
|
-
rhiCapture,
|
|
2668
|
-
...rhiAttachment === void 0 ? {} : { rhiAttachment }
|
|
2669
|
-
});
|
|
2641
|
+
Object.assign(buildArgs, { rhiCapture });
|
|
2670
2642
|
}
|
|
2671
2643
|
if (debugDraw !== void 0) {
|
|
2672
2644
|
Object.assign(buildArgs, { debugDraw });
|
|
@@ -2684,17 +2656,17 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2684
2656
|
const bridgePort = import.meta.env?.VITE_FORGEAX_ENGINE_BRIDGE_PORT ?? "5733";
|
|
2685
2657
|
await pluginContext.plugin({
|
|
2686
2658
|
name: "browser-remote-bridge",
|
|
2687
|
-
inject: ["world", "renderer", "
|
|
2659
|
+
inject: ["world", "renderer", "assets"],
|
|
2688
2660
|
async apply(ctx) {
|
|
2689
|
-
if (ctx.renderer === void 0 || ctx.
|
|
2690
|
-
throw new Error("browser remote bridge requires renderer and
|
|
2661
|
+
if (ctx.renderer === void 0 || ctx.assets === void 0) {
|
|
2662
|
+
throw new Error("browser remote bridge requires renderer and assets services");
|
|
2691
2663
|
}
|
|
2692
2664
|
try {
|
|
2693
2665
|
const bridge = await Promise.resolve().then(() => (init_browser_remote_bridge(), browser_remote_bridge_exports));
|
|
2694
2666
|
const teardown = await bridge.installBrowserRemoteBridge({
|
|
2695
2667
|
world: ctx.world,
|
|
2696
2668
|
renderer: ctx.renderer,
|
|
2697
|
-
assets: ctx.
|
|
2669
|
+
assets: ctx.assets,
|
|
2698
2670
|
runtimeModule: engineRuntimeModule,
|
|
2699
2671
|
...rhiCapture !== void 0 ? { rhiCapture } : {},
|
|
2700
2672
|
...opts?.profiler !== void 0 ? { profiler: opts.profiler } : {},
|
|
@@ -2710,43 +2682,62 @@ async function createAppFromCanvas(canvas, opts, bundler) {
|
|
|
2710
2682
|
}
|
|
2711
2683
|
return built;
|
|
2712
2684
|
}
|
|
2713
|
-
function syncCanvasDrawingBuffer(canvas
|
|
2714
|
-
const size = resolveCanvasDrawingBufferSize(canvas, maxCanvasPixelRatio);
|
|
2715
|
-
if (size === void 0) return { width: canvas.width, height: canvas.height };
|
|
2716
|
-
if (canvas.width !== size.width) canvas.width = size.width;
|
|
2717
|
-
if (canvas.height !== size.height) canvas.height = size.height;
|
|
2718
|
-
return size;
|
|
2719
|
-
}
|
|
2720
|
-
function measureCanvasDrawingBuffer(canvas, maxCanvasPixelRatio) {
|
|
2721
|
-
return resolveCanvasDrawingBufferSize(canvas, maxCanvasPixelRatio) ?? {
|
|
2722
|
-
width: canvas.width,
|
|
2723
|
-
height: canvas.height
|
|
2724
|
-
};
|
|
2725
|
-
}
|
|
2726
|
-
function resolveCanvasDrawingBufferSize(canvas, maxCanvasPixelRatio) {
|
|
2685
|
+
function syncCanvasDrawingBuffer(canvas) {
|
|
2727
2686
|
if (!Number.isFinite(canvas.clientWidth) || !Number.isFinite(canvas.clientHeight) || canvas.clientWidth <= 0 || canvas.clientHeight <= 0)
|
|
2728
|
-
return
|
|
2687
|
+
return;
|
|
2729
2688
|
const hasExplicitCssSize = (canvas.style?.width ?? "") !== "" || (canvas.style?.height ?? "") !== "";
|
|
2730
2689
|
if (!hasExplicitCssSize && canvas.clientWidth === canvas.width && canvas.clientHeight === canvas.height) {
|
|
2731
|
-
return
|
|
2690
|
+
return;
|
|
2732
2691
|
}
|
|
2733
|
-
const
|
|
2734
|
-
const dpr = maxCanvasPixelRatio === void 0 || !Number.isFinite(maxCanvasPixelRatio) || maxCanvasPixelRatio <= 0 ? devicePixelRatio : Math.min(devicePixelRatio, maxCanvasPixelRatio);
|
|
2692
|
+
const dpr = Math.max(1, globalThis.devicePixelRatio || 1);
|
|
2735
2693
|
const previous = syncedCanvasSizes.get(canvas);
|
|
2736
2694
|
const drawingBufferIsTheLayoutMeasurement = previous !== void 0 && canvas.width === previous.drawingWidth && canvas.height === previous.drawingHeight && canvas.clientWidth === previous.drawingWidth && canvas.clientHeight === previous.drawingHeight;
|
|
2737
2695
|
const cssWidth = drawingBufferIsTheLayoutMeasurement ? previous.cssWidth : canvas.clientWidth;
|
|
2738
2696
|
const cssHeight = drawingBufferIsTheLayoutMeasurement ? previous.cssHeight : canvas.clientHeight;
|
|
2739
2697
|
const width = Math.max(1, Math.round(cssWidth * dpr));
|
|
2740
2698
|
const height = Math.max(1, Math.round(cssHeight * dpr));
|
|
2699
|
+
if (canvas.width !== width) canvas.width = width;
|
|
2700
|
+
if (canvas.height !== height) canvas.height = height;
|
|
2741
2701
|
syncedCanvasSizes.set(canvas, {
|
|
2742
2702
|
cssWidth,
|
|
2743
2703
|
cssHeight,
|
|
2744
2704
|
drawingWidth: width,
|
|
2745
2705
|
drawingHeight: height
|
|
2746
2706
|
});
|
|
2747
|
-
|
|
2707
|
+
}
|
|
2708
|
+
function measureCanvasDrawingBuffer(canvas, maxCanvasPixelRatio) {
|
|
2709
|
+
if (!Number.isFinite(canvas.clientWidth) || !Number.isFinite(canvas.clientHeight) || canvas.clientWidth <= 0 || canvas.clientHeight <= 0) {
|
|
2710
|
+
return { width: canvas.width, height: canvas.height };
|
|
2711
|
+
}
|
|
2712
|
+
const hasExplicitCssSize = (canvas.style?.width ?? "") !== "" || (canvas.style?.height ?? "") !== "";
|
|
2713
|
+
if (!hasExplicitCssSize && canvas.clientWidth === canvas.width && canvas.clientHeight === canvas.height) {
|
|
2714
|
+
return { width: canvas.width, height: canvas.height };
|
|
2715
|
+
}
|
|
2716
|
+
const devicePixelRatio = Math.max(1, globalThis.devicePixelRatio || 1);
|
|
2717
|
+
const dpr = maxCanvasPixelRatio === void 0 || !Number.isFinite(maxCanvasPixelRatio) || maxCanvasPixelRatio <= 0 ? devicePixelRatio : Math.min(devicePixelRatio, maxCanvasPixelRatio);
|
|
2718
|
+
const previous = syncedCanvasSizes.get(canvas);
|
|
2719
|
+
const drawingBufferIsTheLayoutMeasurement = previous !== void 0 && canvas.width === previous.drawingWidth && canvas.height === previous.drawingHeight && canvas.clientWidth === previous.drawingWidth && canvas.clientHeight === previous.drawingHeight;
|
|
2720
|
+
const cssWidth = drawingBufferIsTheLayoutMeasurement ? previous.cssWidth : canvas.clientWidth;
|
|
2721
|
+
const cssHeight = drawingBufferIsTheLayoutMeasurement ? previous.cssHeight : canvas.clientHeight;
|
|
2722
|
+
return {
|
|
2723
|
+
width: Math.max(1, Math.round(cssWidth * dpr)),
|
|
2724
|
+
height: Math.max(1, Math.round(cssHeight * dpr))
|
|
2725
|
+
};
|
|
2748
2726
|
}
|
|
2749
2727
|
var syncedCanvasSizes = /* @__PURE__ */ new WeakMap();
|
|
2728
|
+
function syncCameraAspect(world, canvasW, canvasH) {
|
|
2729
|
+
if (canvasW <= 0 || canvasH <= 0) return;
|
|
2730
|
+
const aspect = canvasW / canvasH;
|
|
2731
|
+
const query = world.query({ with: [Camera] }).unwrap();
|
|
2732
|
+
for (const row of query) {
|
|
2733
|
+
const entity = row.entity;
|
|
2734
|
+
const r = world.get(entity, Camera);
|
|
2735
|
+
if (!r.ok) continue;
|
|
2736
|
+
if (r.value.autoAspect !== true) continue;
|
|
2737
|
+
if (r.value.projection !== CAMERA_PROJECTION_PERSPECTIVE) continue;
|
|
2738
|
+
world.set(entity, Camera, { aspect });
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2750
2741
|
async function startRemoteServer(world, renderer, assets, rhiCapture, profiler, execution) {
|
|
2751
2742
|
try {
|
|
2752
2743
|
const remoteServerMod = await import(
|
|
@@ -2772,22 +2763,17 @@ async function startRemoteServer(world, renderer, assets, rhiCapture, profiler,
|
|
|
2772
2763
|
return void 0;
|
|
2773
2764
|
}
|
|
2774
2765
|
async function createAppFromAssemble(args) {
|
|
2775
|
-
const assetAssemblyResult = assembleAppAssetRuntime(args.assetCatalog, args.assetDecoders);
|
|
2776
|
-
if (!assetAssemblyResult.ok) return err(assetAssemblyResult.error);
|
|
2777
|
-
const assetAssembly = assetAssemblyResult.value;
|
|
2778
2766
|
let pluginContext;
|
|
2779
2767
|
try {
|
|
2780
2768
|
pluginContext = await createWorldContext(
|
|
2781
2769
|
args.world,
|
|
2782
2770
|
assembledEngineProfile({
|
|
2783
2771
|
renderer: args.renderer,
|
|
2784
|
-
|
|
2772
|
+
...args.assets === void 0 ? {} : { assets: args.assets },
|
|
2785
2773
|
extensions: args.plugins ?? []
|
|
2786
2774
|
})
|
|
2787
2775
|
);
|
|
2788
2776
|
} catch (cause) {
|
|
2789
|
-
assetAssembly.dispose();
|
|
2790
|
-
assetAssembly.registry.dispose();
|
|
2791
2777
|
return err(
|
|
2792
2778
|
makeAppError2(
|
|
2793
2779
|
"app-plugin-activation-failed",
|
|
@@ -2829,7 +2815,7 @@ async function createAppFromAssemble(args) {
|
|
|
2829
2815
|
const remoteHandle = shouldStartRemote ? await startRemoteServer(
|
|
2830
2816
|
args.world,
|
|
2831
2817
|
args.renderer,
|
|
2832
|
-
|
|
2818
|
+
args.assets,
|
|
2833
2819
|
void 0,
|
|
2834
2820
|
args.profiler,
|
|
2835
2821
|
executionControl
|
|
@@ -2837,7 +2823,6 @@ async function createAppFromAssemble(args) {
|
|
|
2837
2823
|
if (remoteHandle !== void 0) await pluginContext.plugin(remoteServerPlugin(remoteHandle));
|
|
2838
2824
|
const buildArgs = {
|
|
2839
2825
|
renderer: args.renderer,
|
|
2840
|
-
assets: assetAssembly.registry,
|
|
2841
2826
|
world: args.world,
|
|
2842
2827
|
pluginContext,
|
|
2843
2828
|
executionControl,
|
|
@@ -2870,14 +2855,12 @@ async function createAppFromAssemble(args) {
|
|
|
2870
2855
|
async function buildApp(args) {
|
|
2871
2856
|
const {
|
|
2872
2857
|
renderer,
|
|
2873
|
-
assets,
|
|
2874
2858
|
world,
|
|
2875
2859
|
pluginContext,
|
|
2876
2860
|
inputBackend,
|
|
2877
2861
|
audioBackend,
|
|
2878
2862
|
silenceUnhandledErrors,
|
|
2879
2863
|
rhiCapture,
|
|
2880
|
-
rhiAttachment,
|
|
2881
2864
|
debugDraw,
|
|
2882
2865
|
remoteHandle,
|
|
2883
2866
|
profiler
|
|
@@ -2888,6 +2871,7 @@ async function buildApp(args) {
|
|
|
2888
2871
|
const fanout = new ErrorFanoutRegistry(
|
|
2889
2872
|
silenceUnhandledErrors !== void 0 ? { silenceUnhandledErrors } : {}
|
|
2890
2873
|
);
|
|
2874
|
+
let lastError;
|
|
2891
2875
|
const execution = args.executionControl ?? createLocalExecutionControl(
|
|
2892
2876
|
{
|
|
2893
2877
|
...createExecutionReport("main-serial", unavailableExecutionCapabilities("not required")),
|
|
@@ -2913,6 +2897,7 @@ async function buildApp(args) {
|
|
|
2913
2897
|
}
|
|
2914
2898
|
);
|
|
2915
2899
|
function dispatch(e) {
|
|
2900
|
+
lastError = e;
|
|
2916
2901
|
fanout.fire(e);
|
|
2917
2902
|
}
|
|
2918
2903
|
if (args.wireOnLockErrorDispatch) {
|
|
@@ -2930,7 +2915,7 @@ async function buildApp(args) {
|
|
|
2930
2915
|
Object.assign(loopOpts, { profiler });
|
|
2931
2916
|
}
|
|
2932
2917
|
const loop = createFrameLoop(loopOpts);
|
|
2933
|
-
if (rhiCapture !== void 0
|
|
2918
|
+
if (rhiCapture !== void 0) {
|
|
2934
2919
|
bindRhiCaptureFrameDriver(rhiCapture, {
|
|
2935
2920
|
getState: () => loop.getState(),
|
|
2936
2921
|
pause: () => {
|
|
@@ -2946,17 +2931,15 @@ async function buildApp(args) {
|
|
|
2946
2931
|
stepFrame: (deltaSeconds) => loop.stepFrame(deltaSeconds)
|
|
2947
2932
|
});
|
|
2948
2933
|
}
|
|
2949
|
-
let lastError;
|
|
2950
2934
|
let rendererUnsubscribe;
|
|
2951
2935
|
let resumeAfterSurfaceRestore = false;
|
|
2952
2936
|
function subscribeRendererErrors() {
|
|
2953
2937
|
if (rendererUnsubscribe !== void 0) {
|
|
2954
2938
|
return;
|
|
2955
2939
|
}
|
|
2956
|
-
rendererUnsubscribe = renderer.
|
|
2957
|
-
if (
|
|
2958
|
-
|
|
2959
|
-
}
|
|
2940
|
+
rendererUnsubscribe = renderer.subscribe((event) => {
|
|
2941
|
+
if (event.kind !== "error") return;
|
|
2942
|
+
const e = event.error;
|
|
2960
2943
|
dispatch(e);
|
|
2961
2944
|
});
|
|
2962
2945
|
}
|
|
@@ -2968,7 +2951,7 @@ async function buildApp(args) {
|
|
|
2968
2951
|
}
|
|
2969
2952
|
const stub = {
|
|
2970
2953
|
renderer,
|
|
2971
|
-
assets,
|
|
2954
|
+
...args.assets === void 0 ? {} : { assets: args.assets },
|
|
2972
2955
|
world,
|
|
2973
2956
|
execution,
|
|
2974
2957
|
async releaseSurfacePreserveWorld() {
|
|
@@ -3063,7 +3046,7 @@ async function buildApp(args) {
|
|
|
3063
3046
|
loop.setDrawSource(drawSource);
|
|
3064
3047
|
},
|
|
3065
3048
|
/**
|
|
3066
|
-
* Most recent
|
|
3049
|
+
* Most recent dispatched error retained for host self-inspection.
|
|
3067
3050
|
*/
|
|
3068
3051
|
get lastError() {
|
|
3069
3052
|
return lastError;
|
|
@@ -3072,10 +3055,6 @@ async function buildApp(args) {
|
|
|
3072
3055
|
...debugDraw !== void 0 ? { debugDraw } : {},
|
|
3073
3056
|
...remoteHandle !== void 0 ? { remote: remoteHandle } : {}
|
|
3074
3057
|
};
|
|
3075
|
-
const readyResult = await renderer.ready;
|
|
3076
|
-
if (!readyResult.ok) {
|
|
3077
|
-
return err(readyResult.error);
|
|
3078
|
-
}
|
|
3079
3058
|
return ok(stub);
|
|
3080
3059
|
}
|
|
3081
3060
|
function ensureFallbackCamera(world, aspect = 1) {
|
|
@@ -3682,19 +3661,6 @@ async function createToolPreviewHost(options) {
|
|
|
3682
3661
|
const app = appResult.value;
|
|
3683
3662
|
const appErrors = [];
|
|
3684
3663
|
const unsubscribeAppErrors = app.onError((error) => appErrors.push(error));
|
|
3685
|
-
const rendererReady = await app.renderer.ready;
|
|
3686
|
-
if (!rendererReady.ok) {
|
|
3687
|
-
unsubscribeAppErrors();
|
|
3688
|
-
await app.dispose();
|
|
3689
|
-
await runtime.attachment.dispose();
|
|
3690
|
-
removeOwnedCanvas(canvas, ownsCanvas);
|
|
3691
|
-
return err({
|
|
3692
|
-
code: "tool-preview-bootstrap-failed",
|
|
3693
|
-
expected: "the real WebGPU Renderer to finish pipeline initialization before preview frames",
|
|
3694
|
-
hint: rendererReady.error.hint,
|
|
3695
|
-
detail: { phase: "renderer-ready", cause: rendererReady.error }
|
|
3696
|
-
});
|
|
3697
|
-
}
|
|
3698
3664
|
let resourceFacts;
|
|
3699
3665
|
try {
|
|
3700
3666
|
const prepared = await options.prepare?.(app);
|
|
@@ -3719,7 +3685,7 @@ async function createToolPreviewHost(options) {
|
|
|
3719
3685
|
detail: { phase: bootstrapFailure.phase, cause }
|
|
3720
3686
|
});
|
|
3721
3687
|
}
|
|
3722
|
-
const attached = app.renderer.
|
|
3688
|
+
const attached = app.renderer.attach(app.world);
|
|
3723
3689
|
if (!attached.ok) {
|
|
3724
3690
|
unsubscribeAppErrors();
|
|
3725
3691
|
await app.dispose();
|
|
@@ -3980,6 +3946,6 @@ function fitToolPreviewCameraToAabb(aabb, options) {
|
|
|
3980
3946
|
};
|
|
3981
3947
|
}
|
|
3982
3948
|
|
|
3983
|
-
export { APP_ERROR_HINTS, APP_EXPECTED, APP_PHASE_CATALOG, AppError, EXECUTION_CAPABILITY_NAMES, EXECUTION_REPORT_SCHEMA_VERSION, EXECUTION_REQUESTED_TIERS, EXECUTION_TIERS, LOAD_GAME_ERROR_HINTS, LOAD_GAME_EXPECTED, LoadGameError,
|
|
3949
|
+
export { APP_ERROR_HINTS, APP_EXPECTED, APP_PHASE_CATALOG, AppError, EXECUTION_CAPABILITY_NAMES, EXECUTION_REPORT_SCHEMA_VERSION, EXECUTION_REQUESTED_TIERS, EXECUTION_TIERS, LOAD_GAME_ERROR_HINTS, LOAD_GAME_EXPECTED, LoadGameError, createApp, createExecutionReport, createToolPreviewEvidence, createToolPreviewHost, createToolPreviewRecipe, ensureFallbackCamera, executionBootstrapHostPlugin, fitToolPreviewCameraToAabb, gameHostPlugin, inputPlugin, isAppError, isExecutionReport, isLoadGameError, joinResourcePreviewEvidence, joinToolPreviewEvidence, loadBootstrapEntry, loadGame, measureCanvasDrawingBuffer, missingExecutionCapabilities, ownedRendererPlugin, prepareBootstrapEntry, probeExecutionCapabilities, renderFeatureHostPlugin, renderFeaturePlugin, rendererPlugin, replayToolPreviewCapture, selectExecutionTier, syncCanvasDrawingBuffer, unavailableExecutionCapabilities, validateExecutionBootstrapData, validateToolPreviewTrace };
|
|
3984
3950
|
//# sourceMappingURL=index.mjs.map
|
|
3985
3951
|
//# sourceMappingURL=index.mjs.map
|