@forgeax/engine-runtime 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 +65 -83
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/animation-graph-serialize.unit.test.d.ts +2 -0
- package/dist/__tests__/animation-graph-serialize.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts +2 -0
- package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts.map +1 -0
- package/dist/__tests__/asset-error-exhaustive.test-d.d.ts +11 -0
- package/dist/__tests__/asset-error-exhaustive.test-d.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-guid-reverse.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-guid-reverse.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-mounts.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-mounts.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.browser.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.browser.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.dawn.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.listCatalog.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.listCatalog.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.mesh-bin.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.mesh-bin.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.pack-cache.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.pack-cache.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.recursive.spec.d.ts +2 -0
- package/dist/__tests__/asset-registry.recursive.spec.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.unit.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset.unit.test.d.ts +2 -0
- package/dist/__tests__/asset.unit.test.d.ts.map +1 -0
- package/dist/__tests__/audio-load-by-guid.unit.test.d.ts +2 -0
- package/dist/__tests__/audio-load-by-guid.unit.test.d.ts.map +1 -0
- package/dist/__tests__/backend-selection.integration.test.d.ts +2 -0
- package/dist/__tests__/backend-selection.integration.test.d.ts.map +1 -0
- package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts +2 -0
- package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts.map +1 -0
- package/dist/__tests__/builtin-asset-registry.unit.test.d.ts +2 -0
- package/dist/__tests__/builtin-asset-registry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/collect-scene-asset.test.d.ts +1 -2
- package/dist/__tests__/collect-scene-asset.test.d.ts.map +1 -1
- package/dist/__tests__/collect-scene-mount-collapse.test.d.ts +2 -0
- package/dist/__tests__/collect-scene-mount-collapse.test.d.ts.map +1 -0
- package/dist/__tests__/collect-transient-roundtrip.test.d.ts +1 -1
- package/dist/__tests__/collect-transient-roundtrip.test.d.ts.map +1 -1
- package/dist/__tests__/collect-transient-skip.test.d.ts +1 -2
- package/dist/__tests__/collect-transient-skip.test.d.ts.map +1 -1
- package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts +2 -0
- package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts.map +1 -0
- package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts +2 -0
- package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts.map +1 -0
- package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts +2 -0
- package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/draw-published.d.ts +2 -2
- package/dist/__tests__/draw-published.d.ts.map +1 -1
- package/dist/__tests__/dynamic-texture-store.unit.test.d.ts +2 -0
- package/dist/__tests__/dynamic-texture-store.unit.test.d.ts.map +1 -0
- package/dist/__tests__/errors.unit.test.d.ts +2 -0
- package/dist/__tests__/errors.unit.test.d.ts.map +1 -0
- package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts +2 -0
- package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts.map +1 -0
- package/dist/__tests__/fetch-binary-decompress.test.d.ts +2 -0
- package/dist/__tests__/fetch-binary-decompress.test.d.ts.map +1 -0
- package/dist/__tests__/four-path-compression.integration.test.d.ts +2 -0
- package/dist/__tests__/four-path-compression.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts +2 -0
- package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/guid-for-asset.unit.test.d.ts +2 -0
- package/dist/__tests__/guid-for-asset.unit.test.d.ts.map +1 -0
- package/dist/__tests__/handle-migration.test.d.ts +2 -0
- package/dist/__tests__/handle-migration.test.d.ts.map +1 -0
- package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
- package/dist/__tests__/host-custom-kind-contract.test-d.d.ts +2 -0
- package/dist/__tests__/host-custom-kind-contract.test-d.d.ts.map +1 -0
- package/dist/__tests__/host-custom-kind-contract.test.d.ts +2 -0
- package/dist/__tests__/host-custom-kind-contract.test.d.ts.map +1 -0
- package/dist/__tests__/inspect-name.test.d.ts +2 -0
- package/dist/__tests__/inspect-name.test.d.ts.map +1 -0
- package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts +2 -0
- package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts.map +1 -0
- package/dist/__tests__/loadbyguid-payload.unit.test.d.ts +2 -0
- package/dist/__tests__/loadbyguid-payload.unit.test.d.ts.map +1 -0
- package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts +2 -0
- package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts.map +1 -0
- package/dist/__tests__/loader-extract-graceful.test.d.ts +2 -0
- package/dist/__tests__/loader-extract-graceful.test.d.ts.map +1 -0
- package/dist/__tests__/loader-name-survival.test.d.ts +2 -0
- package/dist/__tests__/loader-name-survival.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin-contract.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin-contract.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/new-kind-refs-contract.test.d.ts +2 -0
- package/dist/__tests__/new-kind-refs-contract.test.d.ts.map +1 -0
- package/dist/__tests__/package-promotion.test.d.ts +2 -0
- package/dist/__tests__/package-promotion.test.d.ts.map +1 -0
- package/dist/__tests__/package-rename.test.d.ts +2 -0
- package/dist/__tests__/package-rename.test.d.ts.map +1 -0
- package/dist/__tests__/recover-error-exhaustive.test-d.d.ts +1 -1
- package/dist/__tests__/recover-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts +1 -1
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts +10 -0
- package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts.map +1 -0
- package/dist/__tests__/render-system-extract.unit.test.d.ts +2 -0
- package/dist/__tests__/render-system-extract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/renderer-test-utils.d.ts +10 -0
- package/dist/__tests__/renderer-test-utils.d.ts.map +1 -0
- package/dist/__tests__/renderer.test-d.d.ts +2 -0
- package/dist/__tests__/renderer.test-d.d.ts.map +1 -0
- package/dist/__tests__/resolve-asset-handle-err.test.d.ts +2 -0
- package/dist/__tests__/resolve-asset-handle-err.test.d.ts.map +1 -0
- package/dist/__tests__/resolve-asset-handle.unit.test.d.ts +2 -0
- package/dist/__tests__/resolve-asset-handle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName-fallback.test.d.ts +2 -0
- package/dist/__tests__/resolveName-fallback.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName-null-package.test.d.ts +2 -0
- package/dist/__tests__/resolveName-null-package.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName-unified-entry.test.d.ts +2 -0
- package/dist/__tests__/resolveName-unified-entry.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName.test.d.ts +2 -0
- package/dist/__tests__/resolveName.test.d.ts.map +1 -0
- package/dist/__tests__/roots-to-scene-asset.test.d.ts +1 -1
- package/dist/__tests__/roots-to-scene-asset.test.d.ts.map +1 -1
- package/dist/__tests__/roundtrip-primitive.test.d.ts +2 -0
- package/dist/__tests__/roundtrip-primitive.test.d.ts.map +1 -0
- package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts +2 -0
- package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts.map +1 -0
- package/dist/__tests__/scene-instance-authoring.integration.test.d.ts +2 -0
- package/dist/__tests__/scene-instance-authoring.integration.test.d.ts.map +1 -0
- package/dist/__tests__/scene-mount-fixed-point.test.d.ts +2 -0
- package/dist/__tests__/scene-mount-fixed-point.test.d.ts.map +1 -0
- package/dist/__tests__/scene-mount-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/scene-mount-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/scene-sugar-instantiate.test.d.ts +2 -0
- package/dist/__tests__/scene-sugar-instantiate.test.d.ts.map +1 -0
- package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/serialize-scene-asset.test.d.ts +1 -1
- package/dist/__tests__/serialize-scene-asset.test.d.ts.map +1 -1
- package/dist/__tests__/template-game-default-api-contract.test.d.ts +2 -0
- package/dist/__tests__/template-game-default-api-contract.test.d.ts.map +1 -0
- package/dist/__tests__/tileset-asset-validate.test.d.ts +2 -0
- package/dist/__tests__/tileset-asset-validate.test.d.ts.map +1 -0
- package/dist/__tests__/transcode-fallback.unit.test.d.ts +2 -0
- package/dist/__tests__/transcode-fallback.unit.test.d.ts.map +1 -0
- package/dist/__tests__/transient-runtime-behavior.test.d.ts +2 -0
- package/dist/__tests__/transient-runtime-behavior.test.d.ts.map +1 -0
- package/dist/__tests__/video-loader-consumption.test.d.ts +2 -0
- package/dist/__tests__/video-loader-consumption.test.d.ts.map +1 -0
- package/dist/__tests__/video-loader-smoke.dawn.test.d.ts +2 -0
- package/dist/__tests__/video-loader-smoke.dawn.test.d.ts.map +1 -0
- package/dist/backend-selection.d.ts +13 -0
- package/dist/backend-selection.d.ts.map +1 -0
- package/dist/collect-scene-asset.d.ts +7 -4
- package/dist/collect-scene-asset.d.ts.map +1 -1
- package/dist/createRenderer.d.ts +14 -2
- package/dist/createRenderer.d.ts.map +1 -1
- package/dist/errors/environment.d.ts +1 -1
- package/dist/errors/environment.d.ts.map +1 -1
- package/dist/index.d.ts +20 -82
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +107 -108
- package/dist/index.mjs.map +1 -1
- package/dist/renderer-host.d.ts +9 -0
- package/dist/renderer-host.d.ts.map +1 -0
- package/dist/renderer-host.mjs +62 -0
- package/dist/renderer-host.mjs.map +1 -0
- package/dist/scene-instances/index.d.ts +2 -0
- package/dist/scene-instances/index.d.ts.map +1 -0
- package/dist/scene-utils/mount-override-fold.d.ts +1 -2
- package/dist/scene-utils/mount-override-fold.d.ts.map +1 -1
- package/dist/systems/sprite-animation-tick.d.ts +1 -1
- package/dist/systems/sprite-animation-tick.d.ts.map +1 -1
- package/dist/systems/transparent-sort.d.ts +1 -2
- package/dist/systems/transparent-sort.d.ts.map +1 -1
- package/dist/tilemap-register-validate.d.ts.map +1 -1
- package/package.json +34 -33
- package/src/__tests__/active-camera.unit.test.ts +19 -9
- package/src/__tests__/animation-graph-collect-roundtrip.test.ts +213 -0
- package/src/__tests__/animation-graph-serialize.unit.test.ts +171 -0
- package/src/__tests__/append-injection.test.ts +1 -1
- package/src/__tests__/asset-brand-and-name-retirement.test.ts +102 -0
- package/src/__tests__/asset-error-exhaustive.test-d.ts +62 -0
- package/src/__tests__/asset-registry-guid-reverse.test.ts +608 -0
- package/src/__tests__/asset-registry-hdr-equirect.test.ts +78 -0
- package/src/__tests__/asset-registry-mesh-pack-payload.dawn.test.ts +232 -0
- package/src/__tests__/asset-registry-mounts.test.ts +806 -0
- package/src/__tests__/asset-registry.browser.test.ts +81 -0
- package/src/__tests__/asset-registry.dawn.test.ts +94 -0
- package/src/__tests__/asset-registry.listCatalog.test.ts +170 -0
- package/src/__tests__/asset-registry.mesh-bin.test.ts +316 -0
- package/src/__tests__/asset-registry.pack-cache.test.ts +969 -0
- package/src/__tests__/asset-registry.raw-container-failfast.test.ts +225 -0
- package/src/__tests__/asset-registry.recursive.spec.ts +1397 -0
- package/src/__tests__/asset-registry.unit.test.ts +1030 -0
- package/src/__tests__/asset.unit.test.ts +7107 -0
- package/src/__tests__/audio-load-by-guid.unit.test.ts +126 -0
- package/src/__tests__/backend-selection.integration.test.ts +11 -0
- package/src/__tests__/basis-catalog-dispatch.integration.test.ts +320 -0
- package/src/__tests__/bind-group-cache-keying.test.ts +4 -4
- package/src/__tests__/block-upload-math.unit.test.ts +2 -2
- package/src/__tests__/builtin-asset-registry.unit.test.ts +112 -0
- package/src/__tests__/builtin-shader-register-e2e.test.ts +1 -1
- package/src/__tests__/cache-false-eviction.test.ts +2 -1
- package/src/__tests__/cache-isolation-matrix.test.ts +2 -1
- package/src/__tests__/camera-clear-snapshot-equivalence.unit.test.ts +5 -6
- package/src/__tests__/clamp-to-last.e2e.browser.test.ts +29 -19
- package/src/__tests__/collect-scene-asset.test.ts +49 -52
- package/src/__tests__/collect-scene-mount-collapse.test.ts +391 -0
- package/src/__tests__/collect-subtree.unit.test.ts +1 -2
- package/src/__tests__/collect-transient-children-absent.test.ts +24 -10
- package/src/__tests__/collect-transient-roundtrip.test.ts +44 -20
- package/src/__tests__/collect-transient-skip.test.ts +24 -13
- package/src/__tests__/components.test-d.ts +1 -6
- package/src/__tests__/components.unit.test.ts +20 -19
- package/src/__tests__/composite-skybox-cross-world.browser.test.ts +59 -27
- package/src/__tests__/compressed-texture-physical-extent.integration.test.ts +139 -0
- package/src/__tests__/create-renderer-assembly.integration.test.ts +42 -29
- package/src/__tests__/createRenderer-dispose.test.ts +35 -402
- package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +25 -30
- package/src/__tests__/createRenderer.unit.test.ts +1 -1
- package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +27 -63
- package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +56 -47
- package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +49 -29
- package/src/__tests__/dawn/instances-shadow.dawn.test.ts +26 -15
- package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +13 -14
- package/src/__tests__/dawn/material-alpha.dawn.test.ts +23 -31
- package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +24 -9
- package/src/__tests__/dawn/{mesh-update.dawn.test.ts → mesh-update-dawn.test.ts} +42 -134
- package/src/__tests__/dawn/mipmap-srgb-linear.dawn.test.ts +14 -7
- package/src/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.ts +16 -28
- package/src/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.ts +23 -39
- package/src/__tests__/dawn/upload-texture.dawn.test.ts +198 -0
- package/src/__tests__/dawn/user-handle-mesh-render.dawn.test.ts +12 -14
- package/src/__tests__/dawn/user-mesh-upload.dawn.test.ts +27 -22
- package/src/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.ts +25 -28
- package/src/__tests__/dawn/zero-manifest-ready.dawn.test.ts +10 -11
- package/src/__tests__/demo-sortscope-migration.unit.test.ts +5 -5
- package/src/__tests__/derive-bgl-integration.test.ts +34 -44
- package/src/__tests__/derive-render-data-skin.unit.test.ts +1 -1
- package/src/__tests__/draw-published.ts +11 -4
- package/src/__tests__/dynamic-texture-store.unit.test.ts +190 -0
- package/src/__tests__/equirect-bc6h.integration.test.ts +144 -21
- package/src/__tests__/errors.unit.test.ts +1227 -0
- package/src/__tests__/extract-frames-graceful-degradation.test.ts +3 -7
- package/src/__tests__/extract-frames-merge.test.ts +35 -22
- package/src/__tests__/extract-record-no-hardcoded-texture-fields.test.ts +5 -16
- package/src/__tests__/extract-skin-mismatch.unit.test.ts +322 -0
- package/src/__tests__/fetch-binary-decompress.test.ts +356 -0
- package/src/__tests__/four-path-compression.integration.test.ts +395 -0
- package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +1 -1
- package/src/__tests__/fullscreen-feature-host.dawn.test.ts +80 -0
- package/src/__tests__/fullscreen-post-bgl-depth.test.ts +4 -2
- package/src/__tests__/fullscreen-post-depth-params-arity.test.ts +3 -3
- package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +39 -23
- package/src/__tests__/fullscreen-post-process-pass.unit.test.ts +4 -2
- package/src/__tests__/fxaa-pixel-diff.dawn.test.ts +28 -17
- package/src/__tests__/fxaa-validation-and-resize.dawn.test.ts +29 -18
- package/src/__tests__/fxaa-zero-overhead.dawn.test.ts +16 -12
- package/src/__tests__/geometry.unit.test.ts +525 -159
- package/src/__tests__/glyph-tilemap-worldid.test.ts +1 -1
- package/src/__tests__/gpu-resource-cow-survivor.test.ts +6 -4
- package/src/__tests__/guid-for-asset.unit.test.ts +102 -0
- package/src/__tests__/handle-migration.test.ts +136 -0
- package/src/__tests__/helpers/register-runtime-components.ts +4 -2
- package/src/__tests__/helpers/register-scene-components.ts +1 -1
- package/src/__tests__/host-custom-kind-contract.test-d.ts +47 -0
- package/src/__tests__/host-custom-kind-contract.test.ts +578 -0
- package/src/__tests__/inspect-name.test.ts +139 -0
- package/src/__tests__/instances.test-d.ts +1 -1
- package/src/__tests__/instantiate-mount-deferred-wiring.test.ts +112 -0
- package/src/__tests__/light-casters-9-light.browser.test.ts +73 -76
- package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +7 -10
- package/src/__tests__/light-snapshot.test-d.ts +2 -2
- package/src/__tests__/lights-vec-negative.unit.test.ts +1 -1
- package/src/__tests__/lights.unit.test.ts +31 -511
- package/src/__tests__/loadbyguid-payload.unit.test.ts +117 -0
- package/src/__tests__/loadbyguid-texture-intern.unit.test.ts +213 -0
- package/src/__tests__/loader-extract-graceful.test.ts +146 -0
- package/src/__tests__/loader-name-survival.test.ts +213 -0
- package/src/__tests__/m3-vec-negative.unit.test.ts +3 -2
- package/src/__tests__/material-texture-uv-scale.unit.test.ts +101 -31
- package/src/__tests__/materials.unit.test.ts +10 -27
- package/src/__tests__/mesh-bin-contract.test.ts +28 -0
- package/src/__tests__/mesh-bin-skin-roundtrip.unit.test.ts +149 -0
- package/src/__tests__/mesh-bin.test.ts +38 -0
- package/src/__tests__/mesh-loader-skin-contract.unit.test.ts +120 -0
- package/src/__tests__/mesh-ssbo-grow.unit.test.ts +3 -3
- package/src/__tests__/mip-gate.unit.test.ts +1 -1
- package/src/__tests__/msaa-sprite-pixel-diff.dawn.test.ts +29 -68
- package/src/__tests__/new-kind-refs-contract.test.ts +132 -0
- package/src/__tests__/node-shims.d.ts +4 -6
- package/src/__tests__/package-promotion.test.ts +88 -0
- package/src/__tests__/package-rename.test.ts +103 -0
- package/src/__tests__/pass-selector.unit.test.ts +2 -2
- package/src/__tests__/pbr-pipeline.unit.test.ts +21 -25
- package/src/__tests__/pipeline-builder-msaa.unit.test.ts +6 -9
- package/src/__tests__/pipeline-cache-keying.unit.test.ts +6 -9
- package/src/__tests__/pipeline-spec.test.ts +16 -177
- package/src/__tests__/pipeline.unit.test.ts +154 -1693
- package/src/__tests__/point-light-shadow.dawn.test.ts +33 -42
- package/src/__tests__/point-light-shadow.unit.test.ts +19 -60
- package/src/__tests__/post-process-error-codes.unit.test.ts +4 -1
- package/src/__tests__/post-process-params-component.unit.test.ts +1 -1
- package/src/__tests__/post-process-params-extract.unit.test.ts +2 -5
- package/src/__tests__/postprocess-camera-consistency.test.ts +4 -7
- package/src/__tests__/profiler-assembly.integration.test.ts +1 -1
- package/src/__tests__/propagate-transforms.dawn.test.ts +12 -11
- package/src/__tests__/record-worldid-isolation.test.ts +7 -29
- package/src/__tests__/recover-error-exhaustive.test-d.ts +1 -1
- package/src/__tests__/render-error-exhaustive.test-d.ts +117 -71
- package/src/__tests__/render-feature-assembly.test-d.ts +20 -9
- package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +8 -6
- package/src/__tests__/render-feature-prepared-graphics.browser.test.ts +65 -559
- package/src/__tests__/render-feature-prepared-graphics.dawn.test.ts +57 -544
- package/src/__tests__/render-feature-prepared-graphics.fixture.ts +104 -0
- package/src/__tests__/render-feature-prepared-graphics.integration.test.ts +40 -248
- package/src/__tests__/render-feature-prepared-graphics.regression.integration.test.ts +83 -340
- package/src/__tests__/render-feature-recover.integration.test.ts +9 -49
- package/src/__tests__/render-feature-runtime-surface.test-d.ts +17 -20
- package/src/__tests__/render-schema-consumer.integration.test.ts +20 -13
- package/src/__tests__/render-schema-owner-boundary.unit.test.ts +2 -6
- package/src/__tests__/render-system-cross-world-overlay-queue.test.ts +5 -5
- package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +16 -31
- package/src/__tests__/render-system-extract.test.ts +36 -51
- package/src/__tests__/render-system-extract.unit.test.ts +360 -0
- package/src/__tests__/render-system-fold-bucket.unit.test.ts +3 -5
- package/src/__tests__/render-system-fold-fallback.unit.test.ts +6 -3
- package/src/__tests__/render-system-fold-material.unit.test.ts +3 -5
- package/src/__tests__/render-system-fold-metrics.unit.test.ts +5 -5
- package/src/__tests__/render-system-fold-modegate.unit.test.ts +6 -6
- package/src/__tests__/render-system-fold.dawn.test.ts +7 -5
- package/src/__tests__/render-system-mega.test.ts +292 -190
- package/src/__tests__/render-system-owner-split-contract.test.ts +10 -32
- package/src/__tests__/render-system-record-multi-material-textureview.test.ts +59 -45
- package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +23 -29
- package/src/__tests__/render-system-record.test.ts +398 -235
- package/src/__tests__/render-system-record.unit.test.ts +25 -26
- package/src/__tests__/render-system-skin-bg.unit.test.ts +8 -12
- package/src/__tests__/renderer-consumer.test-d.ts +16 -3
- package/src/__tests__/renderer-health.unit.test.ts +26 -916
- package/src/__tests__/renderer-lifecycle.integration.test.ts +19 -6
- package/src/__tests__/renderer-recover.unit.test.ts +49 -1069
- package/src/__tests__/renderer-result.test-d.ts +19 -9
- package/src/__tests__/renderer-surface.unit.test.ts +3 -5
- package/src/__tests__/renderer-test-utils.ts +56 -0
- package/src/__tests__/renderer.test-d.ts +61 -0
- package/src/__tests__/resolve-asset-handle-err.test.ts +111 -0
- package/src/__tests__/resolve-asset-handle.unit.test.ts +64 -0
- package/src/__tests__/resolve-depth-only-view.test.ts +1 -1
- package/src/__tests__/resolveName-fallback.test.ts +64 -0
- package/src/__tests__/resolveName-null-package.test.ts +38 -0
- package/src/__tests__/resolveName-unified-entry.test.ts +65 -0
- package/src/__tests__/resolveName.test.ts +64 -0
- package/src/__tests__/rhi-null-command-flow.unit.test.ts +56 -260
- package/src/__tests__/rhi-null-renderer-lifecycle.unit.test.ts +41 -169
- package/src/__tests__/roots-to-scene-asset.test.ts +199 -93
- package/src/__tests__/roundtrip-primitive.test.ts +351 -0
- package/src/__tests__/scene-bare-guid-refs-instantiate.test.ts +123 -0
- package/src/__tests__/scene-equirect-roundtrip.test.ts +103 -16
- package/src/__tests__/scene-instance-authoring.integration.test.ts +8 -0
- package/src/__tests__/scene-instance-bridge.integration.test.ts +1 -1
- package/src/__tests__/scene-instance-component.test.ts +1 -1
- package/src/__tests__/scene-mount-fixed-point.test.ts +257 -0
- package/src/__tests__/scene-mount-roundtrip.test.ts +987 -0
- package/src/__tests__/scene-mount-wrapper-roundtrip.test.ts +202 -0
- package/src/__tests__/scene-sugar-instantiate.test.ts +324 -0
- package/src/__tests__/serialize-mounts-roundtrip.test.ts +533 -0
- package/src/__tests__/serialize-scene-asset.test.ts +219 -22
- package/src/__tests__/shadow-caster-empty-schema.test.ts +3 -3
- package/src/__tests__/shadow-csm-cascade-loadop.test.ts +37 -17
- package/src/__tests__/shadow-csm-component.test.ts +3 -5
- package/src/__tests__/shadow-csm-extract.test.ts +2 -100
- package/src/__tests__/shadow-csm-orthoz.test.ts +2 -16
- package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +19 -14
- package/src/__tests__/shadow-csm-tile-consistency.test.ts +32 -26
- package/src/__tests__/shadow-csm-ubo.dawn.test.ts +8 -49
- package/src/__tests__/shadow-csm-ubo.test.ts +3 -25
- package/src/__tests__/shadow-csm-viewport.browser.test.ts +1 -1
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +67 -56
- package/src/__tests__/shadow-m1.dawn.test.ts +8 -9
- package/src/__tests__/shadow-mesh-ssbo-order.test.ts +11 -27
- package/src/__tests__/skin-errors.unit.test.ts +1 -1
- package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +7 -5
- package/src/__tests__/skylight-lazy-projection.test.ts +36 -15
- package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +5 -5
- package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +47 -64
- package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +15 -14
- package/src/__tests__/sprite-lit-extract-branch.test.ts +1 -1
- package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +1 -1
- package/src/__tests__/ssao-bgl.test.ts +16 -9
- package/src/__tests__/ssao-buffers.test.ts +2 -2
- package/src/__tests__/ssao-data.test.ts +2 -2
- package/src/__tests__/ssao-errors.test.ts +1 -1
- package/src/__tests__/ssao-passes.test.ts +68 -392
- package/src/__tests__/ssao-pipelines.test.ts +1 -1
- package/src/__tests__/ssao-uniform-layout.test.ts +8 -6
- package/src/__tests__/stencil-outline-pixel.dawn.test.ts +25 -17
- package/src/__tests__/swap-chain-format.unit.test.ts +5 -7
- package/src/__tests__/systems.unit.test.ts +536 -1326
- package/src/__tests__/template-game-default-api-contract.test.ts +362 -0
- package/src/__tests__/text.unit.test.ts +56 -33
- package/src/__tests__/tilemap-childed-despawn.test.ts +8 -14
- package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +8 -12
- package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +2 -1
- package/src/__tests__/tilemap-chunk-extract.test.ts +13 -17
- package/src/__tests__/tilemap-dirty-rebuild.test.ts +7 -11
- package/src/__tests__/tilemap-material-cache.test.ts +8 -13
- package/src/__tests__/tilemap-multi-atlas.test.ts +12 -32
- package/src/__tests__/tilemap-owner-boundary.unit.test.ts +5 -2
- package/src/__tests__/tilemap-region-pack.test.ts +8 -12
- package/src/__tests__/tilemap-spawn-flip-pivot.test.ts +8 -12
- package/src/__tests__/tilemap-uv-inset.test.ts +11 -14
- package/src/__tests__/tilemap-validate.test.ts +1 -1
- package/src/__tests__/tileset-asset-validate.test.ts +638 -0
- package/src/__tests__/transcode-fallback.unit.test.ts +207 -0
- package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +36 -28
- package/src/__tests__/transient-fields-collect.test.ts +28 -21
- package/src/__tests__/transient-runtime-behavior.test.ts +227 -0
- package/src/__tests__/transparent-sort-tilemap-sprite-interleave.test.ts +4 -4
- package/src/__tests__/variant-selection.unit.test.ts +1 -1
- package/src/__tests__/video-extract-bindgroup.dawn.test.ts +89 -136
- package/src/__tests__/video-loader-consumption.test.ts +86 -0
- package/src/__tests__/video-loader-smoke.dawn.test.ts +60 -0
- package/src/__tests__/view-ubo-layout.browser.test.ts +0 -22
- package/src/__tests__/world-entity-key.test.ts +1 -1
- package/src/__tests__/world-scene-despawn.test.ts +1 -1
- package/src/__tests__/world-scene-instantiate.test.ts +2 -36
- package/src/__tests__/world-scene-nested.test.ts +1 -1
- package/src/__tests__/world-scene-override.test.ts +1 -1
- package/src/backend-selection.ts +69 -0
- package/src/collect-scene-asset.ts +35 -23
- package/src/components/__tests__/camera.test-d.ts +1 -1
- package/src/components/__tests__/camera.test.ts +1 -1
- package/src/components/__tests__/sprite-animation.test-d.ts +2 -2
- package/src/components/__tests__/tile-layer.test-d.ts +1 -1
- package/src/components/__tests__/tile-layer.unit.test.ts +2 -2
- package/src/createRenderer.ts +24 -36
- package/src/errors/environment.ts +1 -1
- package/src/index.ts +51 -113
- package/src/renderer-host.ts +33 -0
- package/src/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.ts +1 -1
- package/src/scene-instances/index.ts +4 -0
- package/src/scene-utils/mount-override-fold.ts +3 -7
- package/src/systems/__tests__/transparent-sort.bench.ts +3 -3
- package/src/systems/sprite-animation-tick.ts +1 -1
- package/src/systems/transparent-sort.ts +38 -38
- package/src/tilemap-register-validate.ts +4 -4
- package/dist/__tests__/bind-group-cache-binding.test.d.ts +0 -2
- package/dist/__tests__/bind-group-cache-binding.test.d.ts.map +0 -1
- package/dist/__tests__/bind-group-cache-frame.test.d.ts +0 -2
- package/dist/__tests__/bind-group-cache-frame.test.d.ts.map +0 -1
- package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts +0 -2
- package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-manifest.d.ts +0 -131
- package/dist/__tests__/fog-producer-manifest.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-pixel-probe.d.ts +0 -42
- package/dist/__tests__/fog-producer-pixel-probe.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-pixel.browser.test.d.ts +0 -2
- package/dist/__tests__/fog-producer-pixel.browser.test.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts +0 -2
- package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-real-fixture.d.ts +0 -5
- package/dist/__tests__/fog-producer-real-fixture.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-vfx-effect.d.ts +0 -3
- package/dist/__tests__/fog-producer-vfx-effect.d.ts.map +0 -1
- package/dist/__tests__/fog-scene-asset.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-scene-asset.integration.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts +0 -2
- package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-resource.test.d.ts +0 -2
- package/dist/__tests__/gpu-resource.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts +0 -2
- package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-buffers.unit.test.d.ts +0 -2
- package/dist/__tests__/hdrp-buffers.unit.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts +0 -2
- package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts +0 -2
- package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts +0 -2
- package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts.map +0 -1
- package/dist/__tests__/hdrp-ssao-boundary.test.d.ts +0 -2
- package/dist/__tests__/hdrp-ssao-boundary.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-ssao-falsification.test.d.ts +0 -2
- package/dist/__tests__/hdrp-ssao-falsification.test.d.ts.map +0 -1
- package/dist/__tests__/helpers/primitive-world.d.ts +0 -8
- package/dist/__tests__/helpers/primitive-world.d.ts.map +0 -1
- package/dist/__tests__/helpers/render-asset-port.d.ts +0 -15
- package/dist/__tests__/helpers/render-asset-port.d.ts.map +0 -1
- package/dist/__tests__/helpers/scene-asset-port.d.ts +0 -9
- package/dist/__tests__/helpers/scene-asset-port.d.ts.map +0 -1
- package/dist/__tests__/material-derived-coordinates.integration.test.d.ts +0 -2
- package/dist/__tests__/material-derived-coordinates.integration.test.d.ts.map +0 -1
- package/dist/__tests__/pipeline-layout-selection.test.d.ts +0 -2
- package/dist/__tests__/pipeline-layout-selection.test.d.ts.map +0 -1
- package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts +0 -2
- package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts.map +0 -1
- package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts +0 -2
- package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts +0 -2
- package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts.map +0 -1
- package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts +0 -2
- package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-caster-membership.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-caster-membership.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-pssm.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-pssm.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-viewport.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-viewport.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-m2.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-m2.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-m3-calibrate.d.ts +0 -83
- package/dist/__tests__/shadow-m3-calibrate.d.ts.map +0 -1
- package/dist/__tests__/shadow-m3.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-m3.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/temporal-off-path.unit.test.d.ts +0 -2
- package/dist/__tests__/temporal-off-path.unit.test.d.ts.map +0 -1
- package/dist/__tests__/video-cache-regression.unit.test.d.ts +0 -2
- package/dist/__tests__/video-cache-regression.unit.test.d.ts.map +0 -1
- package/dist/asset-kind.d.ts +0 -4
- package/dist/asset-kind.d.ts.map +0 -1
- package/dist/errors/sprite-animation.d.ts +0 -3
- package/dist/errors/sprite-animation.d.ts.map +0 -1
- package/dist/scene-asset-port.d.ts +0 -17
- package/dist/scene-asset-port.d.ts.map +0 -1
- package/dist/scene-collect-errors.d.ts +0 -22
- package/dist/scene-collect-errors.d.ts.map +0 -1
- package/dist/shadow-m3-calibrate.d.ts +0 -40
- package/dist/shadow-m3-calibrate.d.ts.map +0 -1
- package/src/__tests__/bind-group-cache-binding.test.ts +0 -2513
- package/src/__tests__/bind-group-cache-frame.test.ts +0 -1511
- package/src/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.ts +0 -204
- package/src/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.ts +0 -297
- package/src/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.ts +0 -271
- package/src/__tests__/dispatch-fullscreen-pass-params.unit.test.ts +0 -321
- package/src/__tests__/fog-producer-manifest.ts +0 -162
- package/src/__tests__/fog-producer-pixel-probe.ts +0 -263
- package/src/__tests__/fog-producer-pixel.browser.test.ts +0 -26
- package/src/__tests__/fog-producer-pixel.dawn.test.ts +0 -55
- package/src/__tests__/fog-producer-real-fixture.ts +0 -805
- package/src/__tests__/fog-producer-vfx-effect.ts +0 -272
- package/src/__tests__/fog-scene-asset.integration.test.ts +0 -123
- package/src/__tests__/gpu-resource-store-cubemap-status.test.ts +0 -207
- package/src/__tests__/gpu-resource.test.ts +0 -1206
- package/src/__tests__/hdrp-bgl-slots.browser.test.ts +0 -50
- package/src/__tests__/hdrp-buffers.unit.test.ts +0 -70
- package/src/__tests__/hdrp-execute-filter.unit.test.ts +0 -200
- package/src/__tests__/hdrp-gbuffer-attachments.browser.test.ts +0 -64
- package/src/__tests__/hdrp-pipeline-asset-type.test-d.ts +0 -139
- package/src/__tests__/hdrp-ssao-boundary.test.ts +0 -237
- package/src/__tests__/hdrp-ssao-falsification.test.ts +0 -289
- package/src/__tests__/helpers/primitive-world.ts +0 -91
- package/src/__tests__/helpers/render-asset-port.ts +0 -65
- package/src/__tests__/helpers/scene-asset-port.ts +0 -23
- package/src/__tests__/material-derived-coordinates.integration.test.ts +0 -100
- package/src/__tests__/pipeline-layout-selection.test.ts +0 -298
- package/src/__tests__/post-process-reads-narrowing.test-d.ts +0 -52
- package/src/__tests__/post-process-register-roundtrip.dawn.test.ts +0 -230
- package/src/__tests__/render-feature-zero-feature.browser.test.ts +0 -152
- package/src/__tests__/render-pipeline-trivial.dawn.test.ts +0 -525
- package/src/__tests__/shadow-csm-caster-membership.test.ts +0 -232
- package/src/__tests__/shadow-csm-pssm.test.ts +0 -142
- package/src/__tests__/shadow-csm-temporal.browser.test.ts +0 -145
- package/src/__tests__/shadow-csm-viewport.test.ts +0 -74
- package/src/__tests__/shadow-m2.dawn.test.ts +0 -394
- package/src/__tests__/shadow-m3-calibrate-run.dawn.test.ts +0 -248
- package/src/__tests__/shadow-m3-calibrate.ts +0 -203
- package/src/__tests__/shadow-m3.dawn.test.ts +0 -288
- package/src/__tests__/shadow-probe-control-flow.dawn.test.ts +0 -264
- package/src/__tests__/shadow-quality-metrics.dawn.test.ts +0 -324
- package/src/__tests__/temporal-off-path.unit.test.ts +0 -69
- package/src/__tests__/video-cache-regression.unit.test.ts +0 -186
- package/src/asset-kind.ts +0 -7
- package/src/errors/sprite-animation.ts +0 -5
- package/src/scene-asset-port.ts +0 -32
- package/src/scene-collect-errors.ts +0 -30
- package/src/shadow-m3-calibrate.ts +0 -171
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as SceneOwner from '@forgeax/engine-scene';
|
|
2
|
+
|
|
1
3
|
// M3 test -- serializeSceneAssetToPack schema-derived field dispatch + fail-fast
|
|
2
4
|
// (plan-strategy D-1/D-2: collect + serialize share same classifier;
|
|
3
5
|
// AC-14: serialize schema-derived refs index + fail-fast on unresolved GUID;
|
|
@@ -8,11 +10,17 @@
|
|
|
8
10
|
// + GUID unresolved fail-fast (AC-14)
|
|
9
11
|
// m3-t2: unregistered component silently skipped, other components intact (AC-15)
|
|
10
12
|
|
|
11
|
-
import {
|
|
12
|
-
import type {
|
|
13
|
+
import { AnimationPlayer } from '@forgeax/engine-animation';
|
|
14
|
+
import type { Asset } from '@forgeax/engine-assets-runtime';
|
|
15
|
+
import { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
16
|
+
import { type Component, defineComponent, type EntityHandle, World } from '@forgeax/engine-ecs';
|
|
17
|
+
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
18
|
+
import { SceneInstance } from '@forgeax/engine-render';
|
|
19
|
+
import type { LocalEntityId, MountOverride, SceneAsset } from '@forgeax/engine-types';
|
|
13
20
|
import { describe, expect, it } from 'vitest';
|
|
14
|
-
import { serializeSceneAssetToPack } from '../collect-scene-asset';
|
|
15
|
-
import '
|
|
21
|
+
import { rootsToSceneAsset, serializeSceneAssetToPack } from '../collect-scene-asset';
|
|
22
|
+
import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
|
|
23
|
+
import { registerSceneComponents } from './helpers/register-scene-components';
|
|
16
24
|
|
|
17
25
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
18
26
|
// Helpers
|
|
@@ -22,6 +30,44 @@ function localId(n: number): LocalEntityId {
|
|
|
22
30
|
return n as LocalEntityId;
|
|
23
31
|
}
|
|
24
32
|
|
|
33
|
+
function mkReg(): AssetRegistry {
|
|
34
|
+
return new AssetRegistry(makeMockShaderRegistry());
|
|
35
|
+
}
|
|
36
|
+
function pg(s: string): AssetGuid {
|
|
37
|
+
const r = AssetGuid.parse(s);
|
|
38
|
+
if (!r.ok) throw new Error(`bad GUID: ${s}`);
|
|
39
|
+
return r.value;
|
|
40
|
+
}
|
|
41
|
+
function catScene(reg: AssetRegistry, g: string, p: SceneAsset): void {
|
|
42
|
+
reg.catalog(pg(g), p as Asset);
|
|
43
|
+
}
|
|
44
|
+
function rs(w: World, a: SceneAsset) {
|
|
45
|
+
registerSceneComponents(w, [AnimationPlayer, W18_ScalarShared]);
|
|
46
|
+
return w.allocSharedRef('SceneAsset', a);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function componentMap(...components: readonly Component[]): ReadonlyMap<string, Component> {
|
|
50
|
+
return new Map(components.map((component) => [component.name, component]));
|
|
51
|
+
}
|
|
52
|
+
function findMountedMember(w: World, rootA: EntityHandle): EntityHandle {
|
|
53
|
+
for (const c of w.iterDescendants(rootA)) {
|
|
54
|
+
if (c === rootA) continue;
|
|
55
|
+
if (!w.get(c, SceneInstance).ok) continue;
|
|
56
|
+
const st = SceneOwner.worldGetSceneInstanceState(w, c);
|
|
57
|
+
if (!st.ok) continue;
|
|
58
|
+
for (const [member] of st.value.entityToLocalId) return member;
|
|
59
|
+
}
|
|
60
|
+
throw new Error('no mounted member found');
|
|
61
|
+
}
|
|
62
|
+
function firstMountOverride(scene: SceneAsset, comp: string): MountOverride | undefined {
|
|
63
|
+
for (const m of scene.mounts ?? []) {
|
|
64
|
+
for (const ov of m.overrides ?? []) {
|
|
65
|
+
if (ov.comp === comp) return ov;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
25
71
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
26
72
|
// m3-t1: serialize refs index with schema derivation (AC-14)
|
|
27
73
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -32,8 +78,6 @@ describe('m3-t1: serialize refs index with schema derivation', () => {
|
|
|
32
78
|
assetRef: { type: 'shared<TestAsset>' },
|
|
33
79
|
// biome-ignore lint/suspicious/noExplicitAny: defineComponent constraint too strict for complex schema types
|
|
34
80
|
} as any);
|
|
35
|
-
const world = new World();
|
|
36
|
-
world.components.register(component).unwrap();
|
|
37
81
|
|
|
38
82
|
const guid1 = 'a0000000-a000-0000-0000-000000000001';
|
|
39
83
|
|
|
@@ -49,7 +93,7 @@ describe('m3-t1: serialize refs index with schema derivation', () => {
|
|
|
49
93
|
|
|
50
94
|
const packResult = serializeSceneAssetToPack(
|
|
51
95
|
sceneAsset,
|
|
52
|
-
|
|
96
|
+
componentMap(component as Component),
|
|
53
97
|
'scene-0000-0000-0000-000000000001',
|
|
54
98
|
);
|
|
55
99
|
expect(packResult.ok).toBe(true);
|
|
@@ -88,8 +132,6 @@ describe('m3-t1: serialize refs index with schema derivation', () => {
|
|
|
88
132
|
sources: { type: 'array<shared<TestAsset>>' },
|
|
89
133
|
// biome-ignore lint/suspicious/noExplicitAny: defineComponent constraint too strict
|
|
90
134
|
} as any);
|
|
91
|
-
const world = new World();
|
|
92
|
-
world.components.register(component).unwrap();
|
|
93
135
|
|
|
94
136
|
const guidA = 'b0000000-b000-0000-0000-000000000001';
|
|
95
137
|
const guidB = 'b0000000-b000-0000-0000-000000000002';
|
|
@@ -106,7 +148,7 @@ describe('m3-t1: serialize refs index with schema derivation', () => {
|
|
|
106
148
|
|
|
107
149
|
const packResult = serializeSceneAssetToPack(
|
|
108
150
|
sceneAsset,
|
|
109
|
-
|
|
151
|
+
componentMap(component as Component),
|
|
110
152
|
'scene-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
|
|
111
153
|
);
|
|
112
154
|
expect(packResult.ok).toBe(true);
|
|
@@ -143,8 +185,6 @@ describe('m3-t1: serialize refs index with schema derivation', () => {
|
|
|
143
185
|
tileset: { type: 'shared<TestAsset>' },
|
|
144
186
|
// biome-ignore lint/suspicious/noExplicitAny: defineComponent constraint too strict
|
|
145
187
|
} as any);
|
|
146
|
-
const world = new World();
|
|
147
|
-
world.components.register(component).unwrap();
|
|
148
188
|
|
|
149
189
|
const tilesetGuid = 'c0000000-c000-0000-0000-000000000001';
|
|
150
190
|
|
|
@@ -160,7 +200,7 @@ describe('m3-t1: serialize refs index with schema derivation', () => {
|
|
|
160
200
|
|
|
161
201
|
const packResult = serializeSceneAssetToPack(
|
|
162
202
|
sceneAsset,
|
|
163
|
-
|
|
203
|
+
componentMap(component as Component),
|
|
164
204
|
'scene-cccc-cccc-cccc-cccccccccccc',
|
|
165
205
|
);
|
|
166
206
|
expect(packResult.ok).toBe(true);
|
|
@@ -181,8 +221,6 @@ describe('m3-t1: serialize refs index with schema derivation', () => {
|
|
|
181
221
|
loneRef: { type: 'shared<TestAsset>' },
|
|
182
222
|
// biome-ignore lint/suspicious/noExplicitAny: defineComponent constraint too strict for complex schema types
|
|
183
223
|
} as any);
|
|
184
|
-
const world = new World();
|
|
185
|
-
world.components.register(component).unwrap();
|
|
186
224
|
|
|
187
225
|
// Use a non-string value in the shared<> field — this bypasses Phase 1 GUID
|
|
188
226
|
// collection (only strings are collected), so Phase 2 index lookup will fail.
|
|
@@ -204,7 +242,7 @@ describe('m3-t1: serialize refs index with schema derivation', () => {
|
|
|
204
242
|
// and the happy path produces ok.
|
|
205
243
|
const packResult = serializeSceneAssetToPack(
|
|
206
244
|
sceneAsset,
|
|
207
|
-
|
|
245
|
+
componentMap(component as Component),
|
|
208
246
|
'scene-dddd-dddd-dddd-dddddddddddd',
|
|
209
247
|
);
|
|
210
248
|
expect(packResult.ok).toBe(true);
|
|
@@ -231,8 +269,6 @@ describe('m3-t2: unregistered component silently skipped', () => {
|
|
|
231
269
|
const component = defineComponent('Test_SRegComp', {
|
|
232
270
|
val: 'f32',
|
|
233
271
|
});
|
|
234
|
-
const world = new World();
|
|
235
|
-
world.components.register(component).unwrap();
|
|
236
272
|
|
|
237
273
|
const sceneAsset: SceneAsset = {
|
|
238
274
|
kind: 'scene',
|
|
@@ -249,7 +285,7 @@ describe('m3-t2: unregistered component silently skipped', () => {
|
|
|
249
285
|
|
|
250
286
|
const packResult = serializeSceneAssetToPack(
|
|
251
287
|
sceneAsset,
|
|
252
|
-
|
|
288
|
+
componentMap(component as Component),
|
|
253
289
|
'scene-eeee-eeee-eeee-eeeeeeeeeeee',
|
|
254
290
|
);
|
|
255
291
|
expect(packResult.ok).toBe(true);
|
|
@@ -286,8 +322,6 @@ describe('m3-t2: unregistered component silently skipped', () => {
|
|
|
286
322
|
const component = defineComponent('Test_SRegComp2', {
|
|
287
323
|
count: 'i32',
|
|
288
324
|
});
|
|
289
|
-
const world = new World();
|
|
290
|
-
world.components.register(component).unwrap();
|
|
291
325
|
|
|
292
326
|
const sceneAsset: SceneAsset = {
|
|
293
327
|
kind: 'scene',
|
|
@@ -304,7 +338,7 @@ describe('m3-t2: unregistered component silently skipped', () => {
|
|
|
304
338
|
|
|
305
339
|
const packResult = serializeSceneAssetToPack(
|
|
306
340
|
sceneAsset,
|
|
307
|
-
|
|
341
|
+
componentMap(component as Component),
|
|
308
342
|
'scene-ffff-ffff-ffff-ffffffffffff',
|
|
309
343
|
);
|
|
310
344
|
expect(packResult.ok).toBe(true);
|
|
@@ -334,3 +368,166 @@ describe('m3-t2: unregistered component silently skipped', () => {
|
|
|
334
368
|
});
|
|
335
369
|
|
|
336
370
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
371
|
+
// w18 — AC-05: collect-side handle→GUID two-state NULL-sentinel in override values
|
|
372
|
+
//
|
|
373
|
+
// Override values carry shared<T> fields (scalar) and array<shared<T>> fields
|
|
374
|
+
// (positional SoA, e.g. AnimationPlayer.clips = [h, 0, 0, 0]). rootsToSceneAsset
|
|
375
|
+
// folds an add-override, then serializes its shared fields by reverse-looking-up
|
|
376
|
+
// each live handle to its catalogued GUID. The NULL-sentinel (handle 0) has two
|
|
377
|
+
// distinct semantics that must survive round-trip (aligned to #640):
|
|
378
|
+
// - scalar shared handle 0 -> field omitted (deserialize restores slot-0 default)
|
|
379
|
+
// - array shared handle 0 -> placeholder 0 kept (positional alignment w/ SoA)
|
|
380
|
+
// A valid handle -> GUID string; a mixed array distinguishes the two per slot.
|
|
381
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
382
|
+
|
|
383
|
+
const W18_CLIP0 = 'a1a1a1a1-1111-4111-8111-111111111111';
|
|
384
|
+
const W18_CLIP1 = 'b2b2b2b2-2222-4222-8222-222222222222';
|
|
385
|
+
const W18_CHILD = 'c3c3c3c3-3333-4333-8333-333333333333';
|
|
386
|
+
const W18_PARENT = 'd4d4d4d4-4444-4444-8444-444444444444';
|
|
387
|
+
const W18_SCALAR = 'e5e5e5e5-5555-4555-8555-555555555555';
|
|
388
|
+
|
|
389
|
+
// A component whose override value carries a scalar shared field, so the scalar
|
|
390
|
+
// NULL-sentinel (omit) vs valid-handle (GUID) branch is exercised.
|
|
391
|
+
const W18_ScalarShared = defineComponent('W18_ScalarShared', {
|
|
392
|
+
asset: { type: 'shared<TestAsset>' },
|
|
393
|
+
tag: 'f32',
|
|
394
|
+
// biome-ignore lint/suspicious/noExplicitAny: defineComponent constraint too strict for shared<>
|
|
395
|
+
} as any) as Component;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Mint a shared handle pointing at the SAME payload object that is catalogued
|
|
399
|
+
* under `guid`, so collect-side `_guidForAsset` reverse-resolves the handle back
|
|
400
|
+
* to `guid` (identity scan, asset-registry.ts _guidForAsset).
|
|
401
|
+
*/
|
|
402
|
+
function mintCatalogued(reg: AssetRegistry, w: World, guid: string, tag: number): number {
|
|
403
|
+
const payload = { kind: 'animation-clip', tag } as unknown as Asset;
|
|
404
|
+
reg.catalog(pg(guid), payload);
|
|
405
|
+
return w.allocSharedRef('AnimationClip', payload) as unknown as number;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** Build parent scene mounting one bare child; instantiate; return root. */
|
|
409
|
+
function mountOne(reg: AssetRegistry, w: World): EntityHandle {
|
|
410
|
+
const child: SceneAsset = {
|
|
411
|
+
kind: 'scene',
|
|
412
|
+
entities: [{ localId: localId(0), components: { Transform: { pos: [1, 0, 0] } } }],
|
|
413
|
+
};
|
|
414
|
+
catScene(reg, W18_CHILD, child);
|
|
415
|
+
const parent: SceneAsset = {
|
|
416
|
+
kind: 'scene',
|
|
417
|
+
entities: [{ localId: localId(0), components: { Transform: { pos: [0, 0, 0] } } }],
|
|
418
|
+
mounts: [{ localId: localId(1), source: W18_CHILD, memberFirst: localId(2), memberCount: 1 }],
|
|
419
|
+
};
|
|
420
|
+
catScene(reg, W18_PARENT, parent);
|
|
421
|
+
const inst = reg.instantiate(rs(w, parent), w);
|
|
422
|
+
if (!inst.ok) throw new Error('instantiate failed');
|
|
423
|
+
return inst.value;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
describe('w18 — override-value shared handle→GUID two-state NULL-sentinel (AC-05)', () => {
|
|
427
|
+
it('(a) array<shared<>> mixed valid handle + NULL sentinel -> GUID string + placeholder 0', () => {
|
|
428
|
+
const reg = mkReg();
|
|
429
|
+
const w = new World();
|
|
430
|
+
const root = mountOne(reg, w);
|
|
431
|
+
const member = findMountedMember(w, root);
|
|
432
|
+
|
|
433
|
+
// clips = [validHandle, 0, 0, 0] — slot 0 active, slots 1-3 NULL sentinel.
|
|
434
|
+
// M1 migration: AnimationPlayer.clips is now variable-length; we explicitly
|
|
435
|
+
// provide the 0-sentinel slots to test the NULL-sentinel round-trip.
|
|
436
|
+
const clipH = mintCatalogued(reg, w, W18_CLIP0, 0);
|
|
437
|
+
const add = w.addComponent(member, {
|
|
438
|
+
component: AnimationPlayer,
|
|
439
|
+
data: { clips: [clipH, 0, 0, 0] } as never,
|
|
440
|
+
});
|
|
441
|
+
expect(add.ok).toBe(true);
|
|
442
|
+
|
|
443
|
+
const collect = rootsToSceneAsset(reg, w, [root]);
|
|
444
|
+
expect(collect.ok).toBe(true);
|
|
445
|
+
if (!collect.ok) return;
|
|
446
|
+
const ov = firstMountOverride(collect.value, 'AnimationPlayer');
|
|
447
|
+
expect(ov).toBeDefined();
|
|
448
|
+
if (!ov) return;
|
|
449
|
+
const clips = (ov.value as Record<string, unknown>).clips as unknown[];
|
|
450
|
+
expect(Array.isArray(clips)).toBe(true);
|
|
451
|
+
// slot 0 -> GUID string; slots 1-3 -> numeric 0 placeholder (positional).
|
|
452
|
+
expect(typeof clips[0]).toBe('string');
|
|
453
|
+
expect(clips[0]).toBe(W18_CLIP0);
|
|
454
|
+
expect(clips[1]).toBe(0);
|
|
455
|
+
expect(clips[2]).toBe(0);
|
|
456
|
+
expect(clips[3]).toBe(0);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
it('(b) array<shared<>> two valid handles at slots 0 and 1 -> two distinct GUIDs', () => {
|
|
460
|
+
const reg = mkReg();
|
|
461
|
+
const w = new World();
|
|
462
|
+
const root = mountOne(reg, w);
|
|
463
|
+
const member = findMountedMember(w, root);
|
|
464
|
+
|
|
465
|
+
const h0 = mintCatalogued(reg, w, W18_CLIP0, 10);
|
|
466
|
+
const h1 = mintCatalogued(reg, w, W18_CLIP1, 11);
|
|
467
|
+
const add = w.addComponent(member, {
|
|
468
|
+
component: AnimationPlayer,
|
|
469
|
+
data: { clips: [h0, h1] } as never,
|
|
470
|
+
});
|
|
471
|
+
expect(add.ok).toBe(true);
|
|
472
|
+
|
|
473
|
+
const collect = rootsToSceneAsset(reg, w, [root]);
|
|
474
|
+
expect(collect.ok).toBe(true);
|
|
475
|
+
if (!collect.ok) return;
|
|
476
|
+
const ov = firstMountOverride(collect.value, 'AnimationPlayer');
|
|
477
|
+
expect(ov).toBeDefined();
|
|
478
|
+
if (!ov) return;
|
|
479
|
+
const clips = (ov.value as Record<string, unknown>).clips as unknown[];
|
|
480
|
+
expect(clips.length).toBe(2);
|
|
481
|
+
expect(clips[0]).toBe(W18_CLIP0);
|
|
482
|
+
expect(clips[1]).toBe(W18_CLIP1);
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
it('(c) scalar shared<> valid handle -> GUID string (non-null branch)', () => {
|
|
486
|
+
expect(W18_ScalarShared.name).toBe('W18_ScalarShared');
|
|
487
|
+
const reg = mkReg();
|
|
488
|
+
const w = new World();
|
|
489
|
+
const root = mountOne(reg, w);
|
|
490
|
+
const member = findMountedMember(w, root);
|
|
491
|
+
|
|
492
|
+
const h = mintCatalogued(reg, w, W18_SCALAR, 0);
|
|
493
|
+
const add = w.addComponent(member, {
|
|
494
|
+
component: W18_ScalarShared,
|
|
495
|
+
data: { asset: h, tag: 7 } as never,
|
|
496
|
+
});
|
|
497
|
+
expect(add.ok).toBe(true);
|
|
498
|
+
|
|
499
|
+
const collect = rootsToSceneAsset(reg, w, [root]);
|
|
500
|
+
expect(collect.ok).toBe(true);
|
|
501
|
+
if (!collect.ok) return;
|
|
502
|
+
const ov = firstMountOverride(collect.value, 'W18_ScalarShared');
|
|
503
|
+
expect(ov).toBeDefined();
|
|
504
|
+
if (!ov) return;
|
|
505
|
+
const val = ov.value as Record<string, unknown>;
|
|
506
|
+
expect(val.asset).toBe(W18_SCALAR); // valid handle -> GUID string
|
|
507
|
+
expect(val.tag).toBe(7);
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
it('(d) scalar shared<> handle 0 -> field omitted (NULL-sentinel branch)', () => {
|
|
511
|
+
const reg = mkReg();
|
|
512
|
+
const w = new World();
|
|
513
|
+
const root = mountOne(reg, w);
|
|
514
|
+
const member = findMountedMember(w, root);
|
|
515
|
+
|
|
516
|
+
const add = w.addComponent(member, {
|
|
517
|
+
component: W18_ScalarShared,
|
|
518
|
+
data: { asset: 0, tag: 3 } as never,
|
|
519
|
+
});
|
|
520
|
+
expect(add.ok).toBe(true);
|
|
521
|
+
|
|
522
|
+
const collect = rootsToSceneAsset(reg, w, [root]);
|
|
523
|
+
expect(collect.ok).toBe(true);
|
|
524
|
+
if (!collect.ok) return;
|
|
525
|
+
const ov = firstMountOverride(collect.value, 'W18_ScalarShared');
|
|
526
|
+
expect(ov).toBeDefined();
|
|
527
|
+
if (!ov) return;
|
|
528
|
+
const val = ov.value as Record<string, unknown>;
|
|
529
|
+
// scalar handle 0 -> field omitted (deserialize restores slot-0 default).
|
|
530
|
+
expect('asset' in val).toBe(false);
|
|
531
|
+
expect(val.tag).toBe(3);
|
|
532
|
+
});
|
|
533
|
+
});
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
import { existsSync, readFileSync } from 'node:fs';
|
|
27
27
|
import { dirname, join } from 'node:path';
|
|
28
28
|
import { fileURLToPath } from 'node:url';
|
|
29
|
-
import { appendInjection } from '@forgeax/engine-render/internal';
|
|
30
29
|
import { derive } from '@forgeax/engine-types';
|
|
31
30
|
import { describe, expect, it } from 'vitest';
|
|
31
|
+
import { appendInjection } from '../../../render/src/pbr-pipeline';
|
|
32
32
|
|
|
33
33
|
const repoRoot = (() => {
|
|
34
34
|
// packages/runtime/src/__tests__/<this file>.ts -> repo root
|
|
@@ -72,8 +72,8 @@ describe('shadow_caster empty schema (M4 w21)', () => {
|
|
|
72
72
|
'packages',
|
|
73
73
|
'render',
|
|
74
74
|
'src',
|
|
75
|
-
'
|
|
76
|
-
'
|
|
75
|
+
'assembly',
|
|
76
|
+
'factory.ts',
|
|
77
77
|
);
|
|
78
78
|
const src = readFileSync(createRendererPath, 'utf8');
|
|
79
79
|
const re =
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// shadow-csm-cascade-loadop.test.ts -
|
|
1
|
+
// shadow-csm-cascade-loadop.test.ts - typed shadow per-cascade depth clear
|
|
2
2
|
// @perf-budget-skip - the two truth-table cases intentionally drive the full renderer call site.
|
|
3
3
|
// M1: per-cascade depth loadOp truth table, asserted against the REAL call site.
|
|
4
4
|
//
|
|
5
|
-
// The
|
|
5
|
+
// The invariant is owned by the typed shadow graph's cascade recording path:
|
|
6
6
|
// buildBeginRenderPassDescriptor(..., 'shadow-caster',
|
|
7
7
|
// { depthLoadOp: cascadeIndex === 0 ? 'clear' : 'load' })
|
|
8
8
|
//
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
// pure builder (that would be tautological — the bug could regress verbatim
|
|
11
11
|
// while the suite stays green). Instead it drives the whole pipeline through
|
|
12
12
|
// createRenderer + renderer.draw([world], { cameraOwner: 0, resourceOwner: 0 }): the URP cascade loop calls
|
|
13
|
-
//
|
|
14
|
-
//
|
|
13
|
+
// one typed shadow pass per cascade, whose execute closure invokes the real
|
|
14
|
+
// encodeDirectionalShadowPass(c, pass, cascadeIndex, viewport). A mock GPU device
|
|
15
15
|
// captures every descriptor handed to beginRenderPass on the dedicated
|
|
16
16
|
// 'render-system-shadow' command encoder, so the asserted truth table is the
|
|
17
17
|
// engine's decision at the real call site — flip the ternary to a constant and
|
|
@@ -21,7 +21,6 @@ import type { World as WorldType } from '@forgeax/engine-ecs';
|
|
|
21
21
|
import type { Renderer as RendererType } from '@forgeax/engine-render';
|
|
22
22
|
import type { Handle } from '@forgeax/engine-types';
|
|
23
23
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
24
|
-
import { TEST_CUBE_HANDLE, withPrimitiveMeshes } from './helpers/primitive-world';
|
|
25
24
|
|
|
26
25
|
const ENGINE = '../createRenderer';
|
|
27
26
|
|
|
@@ -185,17 +184,29 @@ async function importEngine(): Promise<{
|
|
|
185
184
|
opts?: unknown,
|
|
186
185
|
bundler?: unknown,
|
|
187
186
|
) => Promise<{
|
|
188
|
-
|
|
187
|
+
subscribe: (listener: (event: unknown) => void) => () => void;
|
|
189
188
|
draw: (worlds: unknown, opts: { cameraOwner: number; resourceOwner: number }) => void;
|
|
190
|
-
onError: (cb: (err: { code: string }) => void) => () => void;
|
|
191
189
|
}>;
|
|
192
190
|
}> {
|
|
193
|
-
|
|
191
|
+
const engine = (await import(ENGINE)) as {
|
|
192
|
+
createRenderer: (...args: readonly unknown[]) => Promise<unknown>;
|
|
193
|
+
};
|
|
194
|
+
return {
|
|
195
|
+
createRenderer: async (...args: readonly unknown[]) => {
|
|
196
|
+
const result = (await engine.createRenderer(...args)) as
|
|
197
|
+
| { readonly ok: true; readonly value: unknown }
|
|
198
|
+
| { readonly ok: false; readonly error: unknown };
|
|
199
|
+
if (!result.ok) throw result.error;
|
|
200
|
+
return result.value as {
|
|
201
|
+
subscribe: (listener: (event: unknown) => void) => () => void;
|
|
202
|
+
draw: (worlds: unknown, opts: { cameraOwner: number; resourceOwner: number }) => void;
|
|
203
|
+
};
|
|
204
|
+
},
|
|
205
|
+
};
|
|
194
206
|
}
|
|
195
207
|
|
|
196
208
|
async function importEcs(): Promise<{ World: new () => unknown }> {
|
|
197
|
-
|
|
198
|
-
return { World: withPrimitiveMeshes(BaseWorld) } as never;
|
|
209
|
+
return (await import('@forgeax/engine-ecs')) as never;
|
|
199
210
|
}
|
|
200
211
|
|
|
201
212
|
async function importComponents(): Promise<{
|
|
@@ -207,9 +218,9 @@ async function importComponents(): Promise<{
|
|
|
207
218
|
HANDLE_CUBE: Handle<'MeshAsset', 'shared'>;
|
|
208
219
|
}> {
|
|
209
220
|
return {
|
|
210
|
-
...(await import('@forgeax/engine-render
|
|
221
|
+
...(await import('@forgeax/engine-render')),
|
|
211
222
|
...(await import('@forgeax/engine-scene')),
|
|
212
|
-
|
|
223
|
+
...(await import('@forgeax/engine-assets-runtime')),
|
|
213
224
|
} as never;
|
|
214
225
|
}
|
|
215
226
|
|
|
@@ -239,7 +250,6 @@ async function drawCsmScene(cascadeCount: number): Promise<CaptureLog> {
|
|
|
239
250
|
{},
|
|
240
251
|
{ shaderManifestUrl: buildManifestDataUrl() },
|
|
241
252
|
);
|
|
242
|
-
await renderer.ready;
|
|
243
253
|
const { World } = await importEcs();
|
|
244
254
|
const C = await importComponents();
|
|
245
255
|
const world = new (
|
|
@@ -275,8 +285,18 @@ async function drawCsmScene(cascadeCount: number): Promise<CaptureLog> {
|
|
|
275
285
|
);
|
|
276
286
|
|
|
277
287
|
const errors: { code: string }[] = [];
|
|
278
|
-
renderer.
|
|
279
|
-
|
|
288
|
+
renderer.subscribe((event) => {
|
|
289
|
+
if (
|
|
290
|
+
typeof event === 'object' &&
|
|
291
|
+
event !== null &&
|
|
292
|
+
'kind' in event &&
|
|
293
|
+
event.kind === 'error' &&
|
|
294
|
+
'error' in event
|
|
295
|
+
) {
|
|
296
|
+
errors.push(event.error as { code: string });
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
if (!(renderer as unknown as RendererType).attach(world as WorldType).ok) {
|
|
280
300
|
throw new Error('World attachment failed');
|
|
281
301
|
}
|
|
282
302
|
(world as WorldType).update().unwrap();
|
|
@@ -284,7 +304,7 @@ async function drawCsmScene(cascadeCount: number): Promise<CaptureLog> {
|
|
|
284
304
|
return log;
|
|
285
305
|
}
|
|
286
306
|
|
|
287
|
-
describe('CSM per-cascade depth loadOp (
|
|
307
|
+
describe('CSM per-cascade depth loadOp (typed shadow call site)', () => {
|
|
288
308
|
beforeEach(() => {
|
|
289
309
|
vi.stubGlobal('navigator', { ...baseNavigator });
|
|
290
310
|
});
|
|
@@ -295,7 +315,7 @@ describe('CSM per-cascade depth loadOp (real recordShadowPass call site)', () =>
|
|
|
295
315
|
|
|
296
316
|
// ── AC-03: cascadeCount=4 truth table (drives the real call site) ──────────
|
|
297
317
|
// N=4 cascades share a single shadowDepth atlas. Each cascade pass routes
|
|
298
|
-
// through
|
|
318
|
+
// through the typed shadow graph -> beginRenderPass with the per-cascade override.
|
|
299
319
|
// The captured descriptors must read: cascade 0 -> clear + depthClearValue,
|
|
300
320
|
// cascades 1..3 -> load + no depthClearValue.
|
|
301
321
|
|
|
@@ -8,12 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
import { World } from '@forgeax/engine-ecs';
|
|
10
10
|
import { componentDefinition, componentSchema } from '@forgeax/engine-ecs/internal';
|
|
11
|
-
import {
|
|
12
|
-
DirectionalLight,
|
|
13
|
-
ShadowInvalidConfigError,
|
|
14
|
-
validateDirectionalLightData,
|
|
15
|
-
} from '@forgeax/engine-render/internal';
|
|
11
|
+
import { DirectionalLight } from '@forgeax/engine-render';
|
|
16
12
|
import { describe, expect, it } from 'vitest';
|
|
13
|
+
import { validateDirectionalLightData } from '../../../render/src/components/light-helpers';
|
|
14
|
+
import { ShadowInvalidConfigError } from '../../../render/src/errors/render';
|
|
17
15
|
|
|
18
16
|
type DirectionalSpawnResult = ReturnType<World['spawn']>;
|
|
19
17
|
|
|
@@ -12,24 +12,13 @@
|
|
|
12
12
|
// castShadow: true; lightViewProj won't populate.
|
|
13
13
|
|
|
14
14
|
import { World } from '@forgeax/engine-ecs';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
Camera,
|
|
18
|
-
DirectionalLight,
|
|
19
|
-
extractFrame,
|
|
20
|
-
extractFrames,
|
|
21
|
-
MeshFilter,
|
|
22
|
-
MeshRenderer,
|
|
23
|
-
prepareExtractContext,
|
|
24
|
-
} from '@forgeax/engine-render/internal';
|
|
15
|
+
import { Camera, DirectionalLight } from '@forgeax/engine-render';
|
|
25
16
|
import { Transform } from '@forgeax/engine-scene';
|
|
26
17
|
import { describe, expect, it } from 'vitest';
|
|
27
|
-
import {
|
|
28
|
-
import { buildRenderVisibilityViewDescriptors } from '../../../render/src/render-system-extract';
|
|
18
|
+
import { extractFrame, prepareExtractContext } from '../../../render/src/render-system-extract';
|
|
29
19
|
|
|
30
20
|
function makeWorld(castShadow?: boolean): World {
|
|
31
21
|
const world = new World();
|
|
32
|
-
const cubeHandle = world.internSharedRef('MeshAsset', createPrimitiveMesh('cube').unwrap());
|
|
33
22
|
world.spawn({
|
|
34
23
|
component: DirectionalLight,
|
|
35
24
|
data: {
|
|
@@ -47,11 +36,6 @@ function makeWorld(castShadow?: boolean): World {
|
|
|
47
36
|
data: { fov: Math.PI / 4, aspect: 1, near: 0.1, far: 100 },
|
|
48
37
|
},
|
|
49
38
|
);
|
|
50
|
-
world.spawn(
|
|
51
|
-
{ component: Transform, data: { pos: [0, 0, -8] } },
|
|
52
|
-
{ component: MeshFilter, data: { assetHandle: cubeHandle } },
|
|
53
|
-
{ component: MeshRenderer, data: {} },
|
|
54
|
-
);
|
|
55
39
|
return world;
|
|
56
40
|
}
|
|
57
41
|
|
|
@@ -249,86 +233,4 @@ describe('ExtractedLights interface (M2 castShadow gate)', () => {
|
|
|
249
233
|
expect(frame.lights.pcfKernelSize).toBe(3);
|
|
250
234
|
});
|
|
251
235
|
});
|
|
252
|
-
|
|
253
|
-
describe('M3 unified CPU multi-view contract', () => {
|
|
254
|
-
it('publishes four views and structured stable IDs/cascade masks', () => {
|
|
255
|
-
const world = makeWorld(true);
|
|
256
|
-
const frame = extractFrames([world], 0, undefined, undefined, undefined, undefined, {
|
|
257
|
-
cull: 'none',
|
|
258
|
-
});
|
|
259
|
-
const candidates = (frame.candidateRenderables ?? frame.renderables).map(
|
|
260
|
-
(snapshot, candidateIndex) => ({
|
|
261
|
-
stableId: snapshot.entityKey,
|
|
262
|
-
generation: 0,
|
|
263
|
-
candidateIndex,
|
|
264
|
-
worldAabb: undefined,
|
|
265
|
-
casterEligible: true,
|
|
266
|
-
batchId: undefined,
|
|
267
|
-
instanceOrdinal: undefined,
|
|
268
|
-
}),
|
|
269
|
-
);
|
|
270
|
-
const views = buildRenderVisibilityViewDescriptors({
|
|
271
|
-
camera: frame.cameras[0],
|
|
272
|
-
directionalCsm: frame.lights.directionalCsm,
|
|
273
|
-
});
|
|
274
|
-
const evidence = executeCpuMultiViewVisibility({
|
|
275
|
-
views,
|
|
276
|
-
candidates,
|
|
277
|
-
capacityByView: new Map(views.map((view) => [view.viewId, 32] as const)),
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
expect(views.map((view) => view.viewId)).toEqual([
|
|
281
|
-
'main',
|
|
282
|
-
'cascade-0',
|
|
283
|
-
'cascade-1',
|
|
284
|
-
'cascade-2',
|
|
285
|
-
]);
|
|
286
|
-
expect(evidence.views).toHaveLength(4);
|
|
287
|
-
expect(evidence.views[0]?.kind).toBe('main');
|
|
288
|
-
expect(evidence.views.slice(1).every((view) => view.kind === 'cascade')).toBe(true);
|
|
289
|
-
expect(evidence.views[0]?.stableIds).toEqual(
|
|
290
|
-
candidates.map((candidate) => candidate.stableId),
|
|
291
|
-
);
|
|
292
|
-
expect(evidence.cascadeMasks).toHaveLength(candidates.length);
|
|
293
|
-
expect(evidence.cascadeMasks.some((entry) => entry.cascadeMask !== 0)).toBe(true);
|
|
294
|
-
expect(evidence.views.every((view) => view.overflow === false)).toBe(true);
|
|
295
|
-
expect(JSON.parse(JSON.stringify(evidence))).toMatchObject({
|
|
296
|
-
views: expect.arrayContaining([
|
|
297
|
-
expect.objectContaining({ viewId: 'main', stableIds: expect.any(Array) }),
|
|
298
|
-
expect.objectContaining({ viewId: 'cascade-0', compactVisible: expect.any(Array) }),
|
|
299
|
-
]),
|
|
300
|
-
cascadeMasks: expect.any(Array),
|
|
301
|
-
});
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
it('keeps main visibility independent from a caster-only cascade domain', () => {
|
|
305
|
-
const world = makeWorld(true);
|
|
306
|
-
const frame = extractFrames([world], 0, undefined, undefined, undefined, undefined, {
|
|
307
|
-
cull: 'none',
|
|
308
|
-
});
|
|
309
|
-
const source = frame.candidateRenderables ?? frame.renderables;
|
|
310
|
-
const views = buildRenderVisibilityViewDescriptors({
|
|
311
|
-
camera: frame.cameras[0],
|
|
312
|
-
directionalCsm: frame.lights.directionalCsm,
|
|
313
|
-
});
|
|
314
|
-
const evidence = executeCpuMultiViewVisibility({
|
|
315
|
-
views,
|
|
316
|
-
candidates: source.map((snapshot, candidateIndex) => ({
|
|
317
|
-
stableId: snapshot.entityKey,
|
|
318
|
-
generation: 3,
|
|
319
|
-
candidateIndex,
|
|
320
|
-
worldAabb: undefined,
|
|
321
|
-
casterEligible: candidateIndex === 0,
|
|
322
|
-
batchId: undefined,
|
|
323
|
-
instanceOrdinal: undefined,
|
|
324
|
-
})),
|
|
325
|
-
});
|
|
326
|
-
const main = evidence.views.find((view) => view.kind === 'main');
|
|
327
|
-
const cascades = evidence.views.filter((view) => view.kind === 'cascade');
|
|
328
|
-
expect(main?.stableIds).toHaveLength(source.length);
|
|
329
|
-
expect(
|
|
330
|
-
cascades.every((view) => view.stableIds.every((id) => id === source[0]?.entityKey)),
|
|
331
|
-
).toBe(true);
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
236
|
});
|
|
@@ -23,14 +23,10 @@
|
|
|
23
23
|
|
|
24
24
|
import { World } from '@forgeax/engine-ecs';
|
|
25
25
|
import { mat4, vec3 } from '@forgeax/engine-math';
|
|
26
|
-
import {
|
|
27
|
-
Camera,
|
|
28
|
-
DirectionalLight,
|
|
29
|
-
extractFrame,
|
|
30
|
-
prepareExtractContext,
|
|
31
|
-
} from '@forgeax/engine-render/internal';
|
|
26
|
+
import { Camera, DirectionalLight } from '@forgeax/engine-render';
|
|
32
27
|
import { Transform } from '@forgeax/engine-scene';
|
|
33
28
|
import { describe, expect, it } from 'vitest';
|
|
29
|
+
import { extractFrame, prepareExtractContext } from '../../../render/src/render-system-extract';
|
|
34
30
|
|
|
35
31
|
// Light travelling down and toward +x/+z, so the source is up and toward -x/-z.
|
|
36
32
|
const LIGHT_DIR: readonly [number, number, number] = [0.3, -1, 0.3];
|
|
@@ -96,9 +92,6 @@ describe('CSM ortho-Z reaches toward the light (real extract fit, AC-05)', () =>
|
|
|
96
92
|
|
|
97
93
|
const caster = towardLightCaster(6);
|
|
98
94
|
const ground = vec3.create(...GROUND_PT);
|
|
99
|
-
const volumeSet = frame.lights.directionalCsm;
|
|
100
|
-
expect(volumeSet?.volumes).toBe(volumeSet?.cascades);
|
|
101
|
-
expect(volumeSet?.revision).toBeGreaterThan(0);
|
|
102
95
|
|
|
103
96
|
// Find every cascade whose XY footprint covers the GROUND fragment -- that
|
|
104
97
|
// is the cascade `_pickCascadeLayer` will route the ground to. The caster
|
|
@@ -108,13 +101,6 @@ describe('CSM ortho-Z reaches toward the light (real extract fit, AC-05)', () =>
|
|
|
108
101
|
for (let c = 0; c < count; c++) {
|
|
109
102
|
const m = lvp[c];
|
|
110
103
|
if (!(m instanceof Float32Array)) continue;
|
|
111
|
-
const volume = volumeSet?.volumes[c];
|
|
112
|
-
expect(volume?.lightViewProj).toBe(m);
|
|
113
|
-
expect(volume?.rasterLightBounds).toBe(volume?.clipLightBounds);
|
|
114
|
-
expect(volume?.depthLightRange).toEqual([
|
|
115
|
-
volume?.clipLightBounds[4],
|
|
116
|
-
volume?.clipLightBounds[5],
|
|
117
|
-
]);
|
|
118
104
|
const g = projectInto(m, ground);
|
|
119
105
|
if (!g.inXY) continue;
|
|
120
106
|
coveredGroundCascades++;
|