@forgeax/engine-runtime 0.1.27 → 0.1.29
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 +98 -0
- package/dist/collect-scene-asset.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +480 -15
- package/dist/index.mjs.map +1 -1
- package/dist/scene-utils/mount-override-fold.d.ts +3 -1
- package/dist/scene-utils/mount-override-fold.d.ts.map +1 -1
- package/package.json +37 -30
- package/src/__tests__/animation-graph-collect-roundtrip.test.ts +4 -2
- package/src/__tests__/asset-registry-aabb.cases.unit.test.ts +5 -4
- package/src/__tests__/asset-registry-guid-reverse.test.ts +22 -27
- package/src/__tests__/asset-registry-mounts.test.ts +174 -734
- package/src/__tests__/asset-registry-scene.cases.unit.test.ts +9 -18
- package/src/__tests__/asset-registry.recursive.spec.ts +23 -29
- package/src/__tests__/camera-ortho.cases.unit.test.ts +12 -3
- package/src/__tests__/collect-scene-asset.test.ts +96 -113
- package/src/__tests__/collect-scene-mount-collapse.test.ts +64 -66
- package/src/__tests__/collect-transient-children-absent.test.ts +11 -17
- package/src/__tests__/collect-transient-roundtrip.test.ts +12 -13
- package/src/__tests__/collect-transient-skip.test.ts +20 -27
- package/src/__tests__/components.test-d.ts +17 -1
- package/src/__tests__/components.unit.test.ts +75 -27
- package/src/__tests__/composite-skybox-cross-world.browser.test.ts +4 -2
- package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +8 -4
- package/src/__tests__/dawn/instances-shadow.dawn.test.ts +4 -1
- package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +66 -92
- package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +200 -4
- package/src/__tests__/errors.unit.test.ts +13 -0
- package/src/__tests__/feature-depth-material.dawn.test.ts +23 -0
- package/src/__tests__/feature-depth-material.fixture.ts +473 -0
- package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +14 -14
- package/src/__tests__/geometry.unit.test.ts +42 -43
- package/src/__tests__/gpu-resource-release.cases.unit.test.ts +16 -9
- package/src/__tests__/handle-migration.test.ts +0 -1
- package/src/__tests__/instances-renderer-lifecycle.integration.test.ts +20 -14
- package/src/__tests__/instances.test-d.ts +13 -52
- package/src/__tests__/instantiate-mount-deferred-wiring.test.ts +42 -80
- package/src/__tests__/lazy-catalog.cases.unit.test.ts +17 -3
- package/src/__tests__/loader-registry.cases.unit.test.ts +4 -4
- package/src/__tests__/material-publication.browser.test.ts +29 -0
- package/src/__tests__/material-publication.commands.ts +23 -0
- package/src/__tests__/material-publication.dawn.test.ts +24 -0
- package/src/__tests__/material-publication.fixture.ts +349 -0
- package/src/__tests__/material-publication.server.ts +109 -0
- package/src/__tests__/parse-scene-payload-refs.cases.unit.test.ts +73 -96
- package/src/__tests__/pbr-pipeline.unit.test.ts +25 -11
- package/src/__tests__/point-light-shadow.browser.test.ts +8 -2
- package/src/__tests__/point-light-shadow.unit.test.ts +37 -8
- package/src/__tests__/record-all-topology.cases.unit.test.ts +52 -0
- package/src/__tests__/record-draw-branch.cases.unit.test.ts +1 -0
- package/src/__tests__/record-worldid-isolation.test.ts +47 -28
- package/src/__tests__/render-error-exhaustive.test-d.ts +24 -0
- package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +15 -4
- package/src/__tests__/render-system-extract.test.ts +61 -0
- package/src/__tests__/render-system-extract.unit.test.ts +21 -7
- package/src/__tests__/render-system-fold-bucket.unit.test.ts +33 -1
- package/src/__tests__/render-system-fold-material.unit.test.ts +32 -6
- package/src/__tests__/render-system-fold-modegate.unit.test.ts +26 -4
- package/src/__tests__/render-system-fold.dawn.test.ts +4 -1
- package/src/__tests__/render-system-mega.test.ts +50 -62
- package/src/__tests__/renderer-device-loss-provider-feasibility.dawn.test.ts +0 -1
- package/src/__tests__/renderer-device-loss-recovery.dawn.test.ts +0 -3
- package/src/__tests__/renderer-draw-world.cases.unit.test.ts +16 -513
- package/src/__tests__/resolve-scene-guids.cases.unit.test.ts +48 -43
- package/src/__tests__/rhi-null-command-flow.unit.test.ts +9 -7
- package/src/__tests__/roots-to-scene-asset.test.ts +27 -28
- package/src/__tests__/roundtrip-primitive.test.ts +24 -23
- package/src/__tests__/scene-equirect-roundtrip.test.ts +5 -16
- package/src/__tests__/scene-instantiate-cycle-runtime.test.ts +13 -29
- package/src/__tests__/scene-mount-fixed-point.test.ts +104 -227
- package/src/__tests__/scene-mount-roundtrip.test.ts +95 -961
- package/src/__tests__/scene-mount-wrapper-roundtrip.test.ts +36 -182
- package/src/__tests__/scene-sugar-instantiate.test.ts +20 -15
- package/src/__tests__/serialize-mounts-roundtrip.test.ts +108 -492
- package/src/__tests__/serialize-scene-asset.test.ts +36 -50
- package/src/__tests__/shadow-caster-empty-schema.test.ts +3 -1
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +34 -19
- package/src/__tests__/shadow-mesh-ssbo-order.test.ts +5 -12
- package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +6 -4
- package/src/__tests__/skin-m2-extract-happy.cases.unit.test.ts +50 -2
- package/src/__tests__/skin-m2-extract-joint-error.cases.unit.test.ts +50 -2
- package/src/__tests__/skin-m2-extract-null-assets.cases.unit.test.ts +50 -2
- package/src/__tests__/skin-m2-extract-skeleton-error.cases.unit.test.ts +50 -2
- package/src/__tests__/skin-palette-extract.cases.unit.test.ts +2 -0
- package/src/__tests__/skinned-shadow-mixed.dawn.test.ts +93 -48
- package/src/__tests__/skylight-pipeline-layout.cases.unit.test.ts +6 -2
- package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +1 -1
- package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +11 -3
- package/src/__tests__/template-game-default-api-contract.test.ts +21 -21
- package/src/__tests__/tonemap-hdr-target.cases.unit.test.ts +8 -5
- package/src/__tests__/tonemap-pipeline-split.cases.unit.test.ts +3 -0
- package/src/__tests__/transient-fields-collect.test.ts +4 -4
- package/src/__tests__/transient-runtime-behavior.test.ts +9 -9
- package/src/__tests__/vfx-depth-material.dawn.test.ts +42 -0
- package/src/__tests__/vfx-mesh-lighting.browser.test.ts +16 -0
- package/src/__tests__/vfx-mesh-lighting.commands.ts +14 -0
- package/src/__tests__/vfx-mesh-lighting.dawn.test.ts +16 -0
- package/src/__tests__/vfx-mesh-lighting.fixture.ts +883 -0
- package/src/__tests__/wave1-dynamic-geometry.browser.test.ts +326 -0
- package/src/__tests__/wave1-rendering-materials.browser.test.ts +617 -0
- package/src/__tests__/wave1-rendering-p0.browser.test.ts +751 -0
- package/src/__tests__/wave1-rendering-recovery.browser.test.ts +666 -0
- package/src/__tests__/wave1-shadow-diagnostic.browser.test.ts +582 -0
- package/src/__tests__/world-scene-despawn.test.ts +8 -8
- package/src/__tests__/world-scene-instantiate.test.ts +23 -29
- package/src/__tests__/world-scene-nested.test.ts +90 -163
- package/src/__tests__/world-scene-override.test.ts +17 -16
- package/src/__tests__/zero-compression-zero-load.integration.test.ts +1 -0
- package/src/collect-scene-asset.ts +637 -19
- package/src/components/__tests__/sprite-animation.test-d.ts +2 -2
- package/src/index.ts +1 -0
- package/src/scene-utils/mount-override-fold.ts +5 -14
- package/src/__tests__/node-shims.d.ts +0 -31
|
@@ -49,7 +49,7 @@ describe('w1 — AC-07 transient exclusion (SpriteAnimation, VideoPlayer)', () =
|
|
|
49
49
|
expect(collected.ok).toBe(true);
|
|
50
50
|
if (!collected.ok) return;
|
|
51
51
|
|
|
52
|
-
const entity = collected.value.entities[0];
|
|
52
|
+
const entity = Object.values(collected.value.entities)[0];
|
|
53
53
|
expect(entity).toBeDefined();
|
|
54
54
|
if (!entity) return;
|
|
55
55
|
|
|
@@ -80,7 +80,7 @@ describe('w1 — AC-07 transient exclusion (SpriteAnimation, VideoPlayer)', () =
|
|
|
80
80
|
expect(collected.ok).toBe(true);
|
|
81
81
|
if (!collected.ok) return;
|
|
82
82
|
|
|
83
|
-
const entity = collected.value.entities[0];
|
|
83
|
+
const entity = Object.values(collected.value.entities)[0];
|
|
84
84
|
expect(entity).toBeDefined();
|
|
85
85
|
if (!entity) return;
|
|
86
86
|
|
|
@@ -117,7 +117,7 @@ describe('w2 — AC-08 round-trip tests (SpriteAnimation, VideoPlayer)', () => {
|
|
|
117
117
|
expect(collected.ok).toBe(true);
|
|
118
118
|
if (!collected.ok) return;
|
|
119
119
|
|
|
120
|
-
const entity = collected.value.entities[0];
|
|
120
|
+
const entity = Object.values(collected.value.entities)[0];
|
|
121
121
|
expect(entity).toBeDefined();
|
|
122
122
|
if (!entity) return;
|
|
123
123
|
|
|
@@ -173,7 +173,7 @@ describe('w2 — AC-08 round-trip tests (SpriteAnimation, VideoPlayer)', () => {
|
|
|
173
173
|
expect(collected.ok).toBe(true);
|
|
174
174
|
if (!collected.ok) return;
|
|
175
175
|
|
|
176
|
-
const entity = collected.value.entities[0];
|
|
176
|
+
const entity = Object.values(collected.value.entities)[0];
|
|
177
177
|
expect(entity).toBeDefined();
|
|
178
178
|
if (!entity) return;
|
|
179
179
|
|
|
@@ -41,7 +41,7 @@ function makeWorld(): World {
|
|
|
41
41
|
return world;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function
|
|
44
|
+
function _localId(n: number): LocalEntityId {
|
|
45
45
|
return n as LocalEntityId;
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -74,7 +74,7 @@ describe('m3t2 — transient runtime behavior (AC-07)', () => {
|
|
|
74
74
|
// touches the manually-spawned entity
|
|
75
75
|
const asset: SceneAsset = {
|
|
76
76
|
kind: 'scene',
|
|
77
|
-
entities:
|
|
77
|
+
entities: { 'entity-0': { components: {} } },
|
|
78
78
|
};
|
|
79
79
|
cat(reg, '00000000-0000-4000-8000-000000000000', asset);
|
|
80
80
|
const inst = reg.instantiate(rs(world, asset), world);
|
|
@@ -112,7 +112,7 @@ describe('m3t2 — transient runtime behavior (AC-07)', () => {
|
|
|
112
112
|
// Collect an unrelated scene to exercise the collect code path
|
|
113
113
|
const asset: SceneAsset = {
|
|
114
114
|
kind: 'scene',
|
|
115
|
-
entities:
|
|
115
|
+
entities: { 'entity-0': { components: {} } },
|
|
116
116
|
};
|
|
117
117
|
cat(reg, '11111111-1111-4111-8111-111111111111', asset);
|
|
118
118
|
const inst = reg.instantiate(rs(world, asset), world);
|
|
@@ -134,7 +134,7 @@ describe('m3t2 — transient runtime behavior (AC-07)', () => {
|
|
|
134
134
|
|
|
135
135
|
const child: SceneAsset = {
|
|
136
136
|
kind: 'scene',
|
|
137
|
-
entities:
|
|
137
|
+
entities: { 'entity-0': { components: {} } },
|
|
138
138
|
};
|
|
139
139
|
cat(reg, '22222222-2222-4222-8222-222222222222', child);
|
|
140
140
|
const inst = reg.instantiate(rs(world, child), world);
|
|
@@ -171,7 +171,7 @@ describe('m3t2 — transient runtime behavior (AC-07)', () => {
|
|
|
171
171
|
// Collect an unrelated scene
|
|
172
172
|
const asset: SceneAsset = {
|
|
173
173
|
kind: 'scene',
|
|
174
|
-
entities:
|
|
174
|
+
entities: { 'entity-0': { components: {} } },
|
|
175
175
|
};
|
|
176
176
|
cat(reg, '33333333-3333-4333-8333-333333333333', asset);
|
|
177
177
|
const inst = reg.instantiate(rs(world, asset), world);
|
|
@@ -195,10 +195,10 @@ describe('m3t2 — transient runtime behavior (AC-07)', () => {
|
|
|
195
195
|
// The mirror hook should populate Children on entity at localId 0.
|
|
196
196
|
const asset: SceneAsset = {
|
|
197
197
|
kind: 'scene',
|
|
198
|
-
entities:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
198
|
+
entities: {
|
|
199
|
+
'entity-0': { components: { Transform: {} } },
|
|
200
|
+
'entity-1': { components: { Transform: {}, ChildOf: { parent: 'entity-0' } } },
|
|
201
|
+
},
|
|
202
202
|
};
|
|
203
203
|
cat(reg, '44444444-4444-4444-8444-444444444444', asset);
|
|
204
204
|
const inst = reg.instantiate(rs(world, asset), world);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { it } from 'vitest';
|
|
2
|
+
import { particleDepthLayouts, verifyFeatureDepthMaterial } from './feature-depth-material.fixture';
|
|
3
|
+
|
|
4
|
+
// Separate from the synthetic layout suite so each renderer/manifest batch
|
|
5
|
+
// has a bounded process lifetime under the Dawn runner's file isolation.
|
|
6
|
+
const layouts = [
|
|
7
|
+
{ ...particleDepthLayouts[0], particleKind: 'billboard' },
|
|
8
|
+
...(['ribbon', 'trail', 'beam'] as const).map((particleKind) => ({
|
|
9
|
+
...particleDepthLayouts[1],
|
|
10
|
+
particleKind,
|
|
11
|
+
})),
|
|
12
|
+
{ ...particleDepthLayouts[2], particleKind: 'mesh' },
|
|
13
|
+
] as const;
|
|
14
|
+
it.each(
|
|
15
|
+
layouts.flatMap((layout) =>
|
|
16
|
+
(['none', 'material', 'depth'] as const).map((missing) => ({ ...layout, view: true, missing })),
|
|
17
|
+
),
|
|
18
|
+
)(
|
|
19
|
+
'cooks and submits $particleKind with material/depth/input: missing=$missing',
|
|
20
|
+
verifyFeatureDepthMaterial,
|
|
21
|
+
120_000,
|
|
22
|
+
);
|
|
23
|
+
it.each(
|
|
24
|
+
layouts.map((layout) => ({ ...layout, view: true, missing: 'none' as const, inputLane: 3 })),
|
|
25
|
+
)(
|
|
26
|
+
'renders sparse material lane 3 through cooked $particleKind instances',
|
|
27
|
+
verifyFeatureDepthMaterial,
|
|
28
|
+
120_000,
|
|
29
|
+
);
|
|
30
|
+
it.each(
|
|
31
|
+
layouts.map((layout) => ({
|
|
32
|
+
...layout,
|
|
33
|
+
view: true,
|
|
34
|
+
missing: 'none' as const,
|
|
35
|
+
inputLane: 3,
|
|
36
|
+
allInputs: true,
|
|
37
|
+
})),
|
|
38
|
+
)(
|
|
39
|
+
'reads all four distinct material lanes through cooked $particleKind instances',
|
|
40
|
+
verifyFeatureDepthMaterial,
|
|
41
|
+
120_000,
|
|
42
|
+
);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { it } from 'vitest';
|
|
2
|
+
import { commands } from 'vitest/browser';
|
|
3
|
+
import { type CookMeshLightingFixture, verifyVfxMeshLighting } from './vfx-mesh-lighting.fixture';
|
|
4
|
+
|
|
5
|
+
declare module 'vitest/browser' {
|
|
6
|
+
interface BrowserCommands {
|
|
7
|
+
cookVfxMeshLighting: CookMeshLightingFixture;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
it('verifies Mesh Point/IBL parity and depth-dependent shadow latency on WebGPU', async () => {
|
|
12
|
+
await verifyVfxMeshLighting({
|
|
13
|
+
shaderManifestUrl: '/shaders/manifest.json',
|
|
14
|
+
cook: commands.cookVfxMeshLighting,
|
|
15
|
+
});
|
|
16
|
+
}, 120_000);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ok } from '@forgeax/engine-types';
|
|
2
|
+
import { cookParticleCodeEffect, type ParticleCodeModuleSet } from '@forgeax/engine-vfx-compiler';
|
|
3
|
+
|
|
4
|
+
/** Test-host cooking only; no compiler or source evaluation enters the player. */
|
|
5
|
+
export const vfxMeshLightingCommands = {
|
|
6
|
+
async cookVfxMeshLighting(
|
|
7
|
+
_context: unknown,
|
|
8
|
+
source: unknown,
|
|
9
|
+
modules: Readonly<Record<string, ParticleCodeModuleSet>>,
|
|
10
|
+
) {
|
|
11
|
+
const cooked = await cookParticleCodeEffect(source, modules);
|
|
12
|
+
return cooked.ok ? ok({ asset: cooked.value.asset }) : cooked;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs';
|
|
2
|
+
import { env } from 'node:process';
|
|
3
|
+
import { cookParticleCodeEffect } from '@forgeax/engine-vfx-compiler';
|
|
4
|
+
import { buildEngineShaderManifest } from '@forgeax/engine-vite-plugin-shader';
|
|
5
|
+
import { it } from 'vitest';
|
|
6
|
+
import { verifyVfxMeshLighting } from './vfx-mesh-lighting.fixture';
|
|
7
|
+
|
|
8
|
+
it('verifies Mesh Point/IBL parity and depth-dependent shadow latency on Dawn', async () => {
|
|
9
|
+
const manifest = await buildEngineShaderManifest({ pointShadows: true });
|
|
10
|
+
await verifyVfxMeshLighting({
|
|
11
|
+
shaderManifestUrl: `data:application/json,${encodeURIComponent(JSON.stringify(manifest))}`,
|
|
12
|
+
cook: cookParticleCodeEffect,
|
|
13
|
+
tapePaths: env,
|
|
14
|
+
saveTape: writeFileSync,
|
|
15
|
+
});
|
|
16
|
+
}, 120_000);
|