@forgeax/engine-runtime 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 +49 -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 +3 -3
- 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 +19 -81
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +105 -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 +575 -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 +0 -18
- 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 +1203 -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 +16 -500
- 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 +14 -21
- 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 +81 -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 +60 -558
- 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 +59 -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 +43 -261
- 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 +12 -11
- 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 +64 -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 +28 -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 +47 -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
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// tweak-20260627-model-loading-smoke-build-perf M4: regression test for the
|
|
2
|
+
// loadByGuid per-frame texture re-upload bug.
|
|
3
|
+
//
|
|
4
|
+
// SYMPTOM: a MaterialAsset loaded via loadByGuid keeps its texture/sampler
|
|
5
|
+
// values as embedded GUID strings (dash-form). The extract stage
|
|
6
|
+
// (render-system-extract.ts) re-resolved each GUID to a column handle EVERY
|
|
7
|
+
// frame by calling `world.allocSharedRef`, which mints a NEW monotonically-
|
|
8
|
+
// increasing slot id per call. The GPU residency cache
|
|
9
|
+
// (GpuResidencyCache.textureGpuHandles) is keyed on handleSlot(handle), so a
|
|
10
|
+
// fresh slot every frame meant the residency check ALWAYS missed -> all
|
|
11
|
+
// textures re-uploaded to the GPU every frame, GPU memory unbounded, per-frame
|
|
12
|
+
// draw time grew linearly until SIGKILL.
|
|
13
|
+
//
|
|
14
|
+
// FIX: the GUID-string -> column-handle resolution is interned per World, so a
|
|
15
|
+
// given (world, guid, brand) mints EXACTLY ONE stable handle reused across
|
|
16
|
+
// frames (architecture-principle §6 idempotency). This file asserts that
|
|
17
|
+
// invariant directly: resolving the same texture GUID across two extract
|
|
18
|
+
// frames yields the SAME handle, and `world.allocSharedRef` is NOT called again
|
|
19
|
+
// on the second frame's resolution.
|
|
20
|
+
|
|
21
|
+
import { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
22
|
+
import { World } from '@forgeax/engine-ecs';
|
|
23
|
+
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
24
|
+
import { Camera, MeshFilter, MeshRenderer } from '@forgeax/engine-render';
|
|
25
|
+
import { propagateTransforms, Transform } from '@forgeax/engine-scene';
|
|
26
|
+
import type { Handle, MaterialAsset, MeshAsset, TextureAsset } from '@forgeax/engine-types';
|
|
27
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
28
|
+
import { extractFrame, prepareExtractContext } from '../../../render/src/render-system-extract';
|
|
29
|
+
import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
|
|
30
|
+
|
|
31
|
+
function identityTx() {
|
|
32
|
+
return {
|
|
33
|
+
pos: [0, 0, 0],
|
|
34
|
+
quat: [0, 0, 0, 1],
|
|
35
|
+
scale: [1, 1, 1],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function registerQuadMesh(world: World): Handle<'MeshAsset', 'shared'> {
|
|
40
|
+
const positions = new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]);
|
|
41
|
+
return world.allocSharedRef<'MeshAsset', MeshAsset>('MeshAsset', {
|
|
42
|
+
kind: 'mesh',
|
|
43
|
+
vertices: new Float32Array([
|
|
44
|
+
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
|
|
45
|
+
1, 0, 0, 0, 0,
|
|
46
|
+
]),
|
|
47
|
+
indices: new Uint16Array([0, 1, 2]),
|
|
48
|
+
attributes: { position: positions },
|
|
49
|
+
aabb: new Float32Array([0, 0, 0, 1, 1, 1]),
|
|
50
|
+
submeshes: [
|
|
51
|
+
{
|
|
52
|
+
indexOffset: 0,
|
|
53
|
+
indexCount: 3,
|
|
54
|
+
vertexCount: 36,
|
|
55
|
+
topology: 'triangle-list',
|
|
56
|
+
materialSlot: 0,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
|
|
60
|
+
materialSlots: [{ slotName: 'Default' }],
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function textureAsset(red = 255): TextureAsset {
|
|
65
|
+
return {
|
|
66
|
+
kind: 'texture',
|
|
67
|
+
width: 1,
|
|
68
|
+
height: 1,
|
|
69
|
+
format: 'rgba8unorm',
|
|
70
|
+
data: new Uint8Array([red, 255, 255, 255]),
|
|
71
|
+
colorSpace: 'linear',
|
|
72
|
+
mipmap: false,
|
|
73
|
+
} as unknown as TextureAsset;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Build a loadByGuid-shaped scene: the material's baseColorTexture paramValue is
|
|
77
|
+
// an embedded GUID STRING (not a pre-minted numeric handle), catalogued to a
|
|
78
|
+
// texture payload. This is exactly the shape Sponza materials have after
|
|
79
|
+
// loadByGuid, and the shape that triggered the per-frame re-upload bug.
|
|
80
|
+
function spawnTexturedRenderable(world: World, assets: AssetRegistry): { textureGuidStr: string } {
|
|
81
|
+
const mesh = registerQuadMesh(world);
|
|
82
|
+
|
|
83
|
+
// Catalog the texture under a GUID; the material references it by GUID string.
|
|
84
|
+
// The embedded ref must be the EXACT dash-form string that
|
|
85
|
+
// AssetRegistry.lookup keys on (AssetGuid.format, lowercased) -- the same
|
|
86
|
+
// shape loadByGuid leaves in a MaterialAsset's values (D-19).
|
|
87
|
+
const textureGuid = AssetGuid.random();
|
|
88
|
+
const textureGuidStr = AssetGuid.format(textureGuid);
|
|
89
|
+
assets.catalog(textureGuid, textureAsset());
|
|
90
|
+
|
|
91
|
+
const matHandle = world.allocSharedRef<'MaterialAsset', MaterialAsset>('MaterialAsset', {
|
|
92
|
+
kind: 'material',
|
|
93
|
+
passes: [{ name: 'Forward', program: { module: 'forgeax::default-unlit' } }],
|
|
94
|
+
values: {
|
|
95
|
+
baseColor: [1, 1, 1],
|
|
96
|
+
// Embedded GUID string -- the loadByGuid texture-ref shape (D-19).
|
|
97
|
+
baseColorTexture: textureGuidStr,
|
|
98
|
+
},
|
|
99
|
+
} as unknown as MaterialAsset);
|
|
100
|
+
|
|
101
|
+
world
|
|
102
|
+
.spawn(
|
|
103
|
+
{ component: Transform, data: { ...identityTx(), pos: [0, 0, 5] } },
|
|
104
|
+
{
|
|
105
|
+
component: Camera,
|
|
106
|
+
data: {
|
|
107
|
+
fov: Math.PI / 4,
|
|
108
|
+
aspect: 1,
|
|
109
|
+
near: 0.1,
|
|
110
|
+
far: 100,
|
|
111
|
+
projection: 0,
|
|
112
|
+
left: -1,
|
|
113
|
+
right: 1,
|
|
114
|
+
bottom: -1,
|
|
115
|
+
top: 1,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
)
|
|
119
|
+
.unwrap();
|
|
120
|
+
world
|
|
121
|
+
.spawn(
|
|
122
|
+
{ component: Transform, data: identityTx() },
|
|
123
|
+
{ component: MeshFilter, data: { assetHandle: mesh } },
|
|
124
|
+
{ component: MeshRenderer, data: { materials: [matHandle] } },
|
|
125
|
+
)
|
|
126
|
+
.unwrap();
|
|
127
|
+
propagateTransforms(world);
|
|
128
|
+
|
|
129
|
+
return { textureGuidStr };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function baseColorHandleFromFrame(world: World, assets: AssetRegistry): number | undefined {
|
|
133
|
+
const frame = extractFrame(world, prepareExtractContext(world, { assets, pipelineState: null }));
|
|
134
|
+
const renderable = frame.renderables.find(
|
|
135
|
+
(r) => r.material.materialShaderId === 'forgeax::default-unlit',
|
|
136
|
+
);
|
|
137
|
+
const snap = renderable?.material as
|
|
138
|
+
| { readonly baseColorTexture?: Handle<'TextureAsset', 'shared'> }
|
|
139
|
+
| undefined;
|
|
140
|
+
return snap?.baseColorTexture as unknown as number | undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
describe('M4 loadByGuid texture handle interning (per-frame re-upload regression)', () => {
|
|
144
|
+
it('resolves the same texture GUID to the SAME column handle across two extract frames', () => {
|
|
145
|
+
const world = new World();
|
|
146
|
+
const assets = new AssetRegistry(makeMockShaderRegistry());
|
|
147
|
+
spawnTexturedRenderable(world, assets);
|
|
148
|
+
|
|
149
|
+
const handleFrame1 = baseColorHandleFromFrame(world, assets);
|
|
150
|
+
const handleFrame2 = baseColorHandleFromFrame(world, assets);
|
|
151
|
+
|
|
152
|
+
expect(handleFrame1).toBeDefined();
|
|
153
|
+
expect(handleFrame2).toBeDefined();
|
|
154
|
+
// The whole fix: a stable handle across frames so handleSlot(handle) is
|
|
155
|
+
// stable and the GPU residency cache hits instead of re-uploading.
|
|
156
|
+
expect(handleFrame2).toBe(handleFrame1);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('does NOT call world.allocSharedRef again when re-resolving the same GUID on a later frame', () => {
|
|
160
|
+
const world = new World();
|
|
161
|
+
const assets = new AssetRegistry(makeMockShaderRegistry());
|
|
162
|
+
spawnTexturedRenderable(world, assets);
|
|
163
|
+
|
|
164
|
+
// Warm the intern cache (frame 1 mints the texture handle exactly once).
|
|
165
|
+
baseColorHandleFromFrame(world, assets);
|
|
166
|
+
|
|
167
|
+
// Frame 2: spy on allocSharedRef and confirm the GUID resolution is served
|
|
168
|
+
// from the intern cache -- zero new allocations for the cached texture GUID.
|
|
169
|
+
const allocSpy = vi.spyOn(world, 'allocSharedRef');
|
|
170
|
+
const handleFrame2 = baseColorHandleFromFrame(world, assets);
|
|
171
|
+
expect(handleFrame2).toBeDefined();
|
|
172
|
+
|
|
173
|
+
const textureAllocCalls = allocSpy.mock.calls.filter((c) => c[0] === 'TextureAsset');
|
|
174
|
+
expect(textureAllocCalls.length).toBe(0);
|
|
175
|
+
allocSpy.mockRestore();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('retires the cached allocation grant when the GUID is re-catalogued', () => {
|
|
179
|
+
const world = new World();
|
|
180
|
+
const assets = new AssetRegistry(makeMockShaderRegistry());
|
|
181
|
+
const { textureGuidStr } = spawnTexturedRenderable(world, assets);
|
|
182
|
+
|
|
183
|
+
const oldHandle = baseColorHandleFromFrame(world, assets);
|
|
184
|
+
expect(oldHandle).toBeDefined();
|
|
185
|
+
const replacement = textureAsset(127);
|
|
186
|
+
assets.catalog(textureGuidStr, replacement);
|
|
187
|
+
|
|
188
|
+
const newHandle = baseColorHandleFromFrame(world, assets);
|
|
189
|
+
expect(newHandle).toBeDefined();
|
|
190
|
+
expect(newHandle).not.toBe(oldHandle);
|
|
191
|
+
expect(
|
|
192
|
+
world.sharedRefs.resolve(newHandle as unknown as Handle<'TextureAsset', 'shared'>),
|
|
193
|
+
).toMatchObject({ ok: true, value: replacement });
|
|
194
|
+
expect(
|
|
195
|
+
world.sharedRefs.refcount(oldHandle as unknown as Handle<'TextureAsset', 'shared'>),
|
|
196
|
+
).toBe(0);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('drops the cached allocation grant when the GUID is invalidated', () => {
|
|
200
|
+
const world = new World();
|
|
201
|
+
const assets = new AssetRegistry(makeMockShaderRegistry());
|
|
202
|
+
const { textureGuidStr } = spawnTexturedRenderable(world, assets);
|
|
203
|
+
|
|
204
|
+
const handle = baseColorHandleFromFrame(world, assets);
|
|
205
|
+
expect(handle).toBeDefined();
|
|
206
|
+
assets.invalidate(textureGuidStr);
|
|
207
|
+
|
|
208
|
+
expect(baseColorHandleFromFrame(world, assets)).toBeUndefined();
|
|
209
|
+
expect(world.sharedRefs.refcount(handle as unknown as Handle<'TextureAsset', 'shared'>)).toBe(
|
|
210
|
+
0,
|
|
211
|
+
);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// loader-extract-graceful.test.ts -- M4 / w24 integration test for the
|
|
2
|
+
// paramSchema-driven loader/extract handoff.
|
|
3
|
+
//
|
|
4
|
+
// feat-20260613-material-paramschema-driven-binding M4 / w24.
|
|
5
|
+
//
|
|
6
|
+
// Decision anchors (plan-strategy section 2 + section 5.3):
|
|
7
|
+
// - D-5 loader does not pre-filter texture fields by hardcoded name; the
|
|
8
|
+
// paramSchema-derived textureFieldNames is the SSOT. Cross-worktree
|
|
9
|
+
// shader-late-register falls back to "try every int paramValue"
|
|
10
|
+
// gracefully; the extract layer's paramSchema validation catches
|
|
11
|
+
// misclassifications and routes through MISSING_TEXTURE_HANDLE.
|
|
12
|
+
// - R-4 shader-late-register risk: material loaded before its shader is
|
|
13
|
+
// registered. The graceful fallback keeps the load path live.
|
|
14
|
+
//
|
|
15
|
+
// Four scenarios (plan-strategy section 5.3 acceptance), updated for
|
|
16
|
+
// feat-20260614 M8 (D-19): the loader no longer resolves a texture-typed
|
|
17
|
+
// paramValue to a runtime handle. It maps the refs[] index to the embedded
|
|
18
|
+
// sub-asset GUID string; the ECS/render side resolves GUID -> column handle
|
|
19
|
+
// at use time (world.allocSharedRef). `LoadContext.resolveRefSync` is gone.
|
|
20
|
+
// (1) shader registered + texture-typed paramValue + valid refs[] index
|
|
21
|
+
// -> loader rewrites the field to the refs[] GUID string.
|
|
22
|
+
// (2) shader registered + texture-typed paramValue + index out of range
|
|
23
|
+
// -> loader drops the field; record stage falls back to MISSING_TEXTURE_HANDLE.
|
|
24
|
+
// (3) shader NOT registered yet (cross-worktree R-4) + int paramValue
|
|
25
|
+
// -> graceful fallback resolves every in-range int to its refs[] GUID.
|
|
26
|
+
// (4) shader registered + scalar-typed paramValue (metallic = 0) whose
|
|
27
|
+
// value happens to land in [0, refs.length) -> paramSchema-aware path
|
|
28
|
+
// skips it; the field stays as the original int.
|
|
29
|
+
|
|
30
|
+
import { materialLoader } from '@forgeax/engine-assets-runtime';
|
|
31
|
+
import type { LoadContext, ParamSchemaEntry } from '@forgeax/engine-types';
|
|
32
|
+
import { derive } from '@forgeax/engine-types';
|
|
33
|
+
import { describe, expect, it } from 'vitest';
|
|
34
|
+
|
|
35
|
+
function makeCtx(opts: {
|
|
36
|
+
shaderTextureFieldNames?: (shaderId: string) => ReadonlySet<string> | undefined;
|
|
37
|
+
}): LoadContext {
|
|
38
|
+
const ctx: LoadContext = {
|
|
39
|
+
fetchBinary: async () => ({ ok: false as const, error: new Error('no binary') }),
|
|
40
|
+
resolveRef: async () => ({ ok: false as const, error: new Error('no ref') }),
|
|
41
|
+
transcodeCaps: { bc: false, etc2: false, astc: false },
|
|
42
|
+
device: undefined,
|
|
43
|
+
};
|
|
44
|
+
if (opts.shaderTextureFieldNames) {
|
|
45
|
+
ctx.getMaterialShaderTextureFieldNames = opts.shaderTextureFieldNames;
|
|
46
|
+
}
|
|
47
|
+
return ctx;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const standardPbrSchema: readonly ParamSchemaEntry[] = [
|
|
51
|
+
{ name: 'baseColor', type: 'color', default: [1, 1, 1, 1] },
|
|
52
|
+
{ name: 'metallic', type: 'f32', default: 0 },
|
|
53
|
+
{ name: 'roughness', type: 'f32', default: 0.5 },
|
|
54
|
+
{ name: 'baseColorTexture', type: 'texture2d' },
|
|
55
|
+
{ name: 'normalTexture', type: 'texture2d' },
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
describe('loader-extract graceful handoff (M4 w24)', () => {
|
|
59
|
+
it('(1) shader registered + valid texture refs[] index resolves to a structured texture value', () => {
|
|
60
|
+
const textureFields = derive(standardPbrSchema).textureFieldNames;
|
|
61
|
+
const ctx = makeCtx({
|
|
62
|
+
shaderTextureFieldNames: (id) =>
|
|
63
|
+
id === 'forgeax::default-standard-pbr' ? textureFields : undefined,
|
|
64
|
+
});
|
|
65
|
+
const out = materialLoader.load(
|
|
66
|
+
{
|
|
67
|
+
passes: [{ program: { module: 'forgeax::default-standard-pbr' } }],
|
|
68
|
+
values: { baseColorTexture: 0, metallic: 0.5 },
|
|
69
|
+
},
|
|
70
|
+
['tex-bc-guid'],
|
|
71
|
+
ctx,
|
|
72
|
+
);
|
|
73
|
+
expect(out).toMatchObject({ kind: 'material' });
|
|
74
|
+
const pv = (out as { values: Record<string, unknown> }).values;
|
|
75
|
+
// D-19: texture field rewritten to the structured asset value (not a handle).
|
|
76
|
+
expect(pv.baseColorTexture).toEqual({ texture: 'tex-bc-guid' });
|
|
77
|
+
// Scalar field unchanged.
|
|
78
|
+
expect(pv.metallic).toBe(0.5);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('(2) shader registered + texture refs[] index out of range -> field dropped', () => {
|
|
82
|
+
const textureFields = derive(standardPbrSchema).textureFieldNames;
|
|
83
|
+
const ctx = makeCtx({
|
|
84
|
+
shaderTextureFieldNames: (id) =>
|
|
85
|
+
id === 'forgeax::default-standard-pbr' ? textureFields : undefined,
|
|
86
|
+
});
|
|
87
|
+
const out = materialLoader.load(
|
|
88
|
+
{
|
|
89
|
+
passes: [{ program: { module: 'forgeax::default-standard-pbr' } }],
|
|
90
|
+
// index 5 is out of range for refs.length=1 -> dropped.
|
|
91
|
+
values: { baseColorTexture: 5 },
|
|
92
|
+
},
|
|
93
|
+
['tex-bc-guid'],
|
|
94
|
+
ctx,
|
|
95
|
+
);
|
|
96
|
+
expect(out).toMatchObject({ kind: 'material' });
|
|
97
|
+
const pv = (out as { values: Record<string, unknown> }).values;
|
|
98
|
+
// Loader drops the field; record stage falls back to MISSING_TEXTURE_HANDLE.
|
|
99
|
+
expect('baseColorTexture' in pv).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('(3) shader NOT registered (R-4 cross-worktree) -> graceful "try every int" fallback', () => {
|
|
103
|
+
// No paramSchema lookup available -> getMaterialShaderTextureFieldNames
|
|
104
|
+
// returns undefined for every shader id.
|
|
105
|
+
const ctx = makeCtx({
|
|
106
|
+
shaderTextureFieldNames: () => undefined,
|
|
107
|
+
});
|
|
108
|
+
const out = materialLoader.load(
|
|
109
|
+
{
|
|
110
|
+
passes: [{ program: { module: 'forgeax::user-defined' } }],
|
|
111
|
+
values: { customTexture: 0 },
|
|
112
|
+
},
|
|
113
|
+
['tex-guid'],
|
|
114
|
+
ctx,
|
|
115
|
+
);
|
|
116
|
+
expect(out).toMatchObject({ kind: 'material' });
|
|
117
|
+
const pv = (out as { values: Record<string, unknown> }).values;
|
|
118
|
+
// Graceful fallback resolves any in-range int to its refs[] GUID string.
|
|
119
|
+
expect(pv.customTexture).toBe('tex-guid');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('(4) shader registered + scalar paramValue with refs[] index in range -> NOT misclassified', () => {
|
|
123
|
+
const textureFields = derive(standardPbrSchema).textureFieldNames;
|
|
124
|
+
const ctx = makeCtx({
|
|
125
|
+
shaderTextureFieldNames: (id) =>
|
|
126
|
+
id === 'forgeax::default-standard-pbr' ? textureFields : undefined,
|
|
127
|
+
});
|
|
128
|
+
const out = materialLoader.load(
|
|
129
|
+
{
|
|
130
|
+
passes: [{ program: { module: 'forgeax::default-standard-pbr' } }],
|
|
131
|
+
// metallic = 0 is an int in [0, refs.length=1) — would misclassify
|
|
132
|
+
// under a naive "try every int" loader. paramSchema-aware path
|
|
133
|
+
// declares metallic as 'f32', so it skips resolution.
|
|
134
|
+
values: { baseColorTexture: 0, metallic: 0 },
|
|
135
|
+
},
|
|
136
|
+
['tex-bc-guid'],
|
|
137
|
+
ctx,
|
|
138
|
+
);
|
|
139
|
+
expect(out).toMatchObject({ kind: 'material' });
|
|
140
|
+
const pv = (out as { values: Record<string, unknown> }).values;
|
|
141
|
+
// Texture field still resolves to the structured asset value.
|
|
142
|
+
expect(pv.baseColorTexture).toEqual({ texture: 'tex-bc-guid' });
|
|
143
|
+
// Scalar field unchanged: metallic stays 0.
|
|
144
|
+
expect(pv.metallic).toBe(0);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// loader name survival through JSON roundtrip — AC-08 (feat-20260618 w20).
|
|
2
|
+
//
|
|
3
|
+
// Red-first: written before w15 wires entry.name -> registerPackage.
|
|
4
|
+
//
|
|
5
|
+
// dawn smoke walks the in-memory register path and skips the
|
|
6
|
+
// JSON.stringify -> fetch -> JSON.parse pack-body path (AGENTS.md smoke gate +
|
|
7
|
+
// memory typed-array-json-roundtrip-asymmetric-loader-contract). This test
|
|
8
|
+
// drives the prod loadByGuid path with a JSON-roundtripped pack-index so a name
|
|
9
|
+
// that does not survive the roundtrip is caught here.
|
|
10
|
+
//
|
|
11
|
+
// Coverage:
|
|
12
|
+
// AC-08 sync — two meshes sharing a .pack.json, each with a pack-index name;
|
|
13
|
+
// after loadByGuid (parseAssetPayload sync branch) resolveName
|
|
14
|
+
// returns each stored name.
|
|
15
|
+
// AC-08 async — a texture in its own (single-asset) package; after loadByGuid
|
|
16
|
+
// (texture upstream async branch) resolveName returns the
|
|
17
|
+
// basename derived from its package path. Without the entry ->
|
|
18
|
+
// Package wiring the texture would land in a null package and
|
|
19
|
+
// resolveName would be '' -- so basename here still proves the
|
|
20
|
+
// async load path registered the package post-roundtrip.
|
|
21
|
+
// FALSIFY — the same pack with the entry name stripped degrades to
|
|
22
|
+
// basename(path), proving the assertion is name-sensitive (not
|
|
23
|
+
// a tautology). The FALSIFY block does not gate CI; it documents
|
|
24
|
+
// discriminating power.
|
|
25
|
+
|
|
26
|
+
import { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
27
|
+
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
28
|
+
import type { MeshAsset as TypesMeshAsset } from '@forgeax/engine-types';
|
|
29
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
30
|
+
import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
|
|
31
|
+
|
|
32
|
+
const MESH_A = '70000000-0000-4000-7000-000000000001';
|
|
33
|
+
const MESH_B = '70000000-0000-4000-7000-000000000002';
|
|
34
|
+
const TEX = '70000000-0000-4000-7000-0000000000aa';
|
|
35
|
+
const SHARED_PACK_URL = '/packs/char.pack.json';
|
|
36
|
+
const TEX_URL = '/assets/diffuse.pack.json';
|
|
37
|
+
|
|
38
|
+
function parseGuid(s: string): AssetGuid {
|
|
39
|
+
const r = AssetGuid.parse(s);
|
|
40
|
+
if (!r.ok) throw new Error(`invalid test GUID: ${s}`);
|
|
41
|
+
return r.value;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function makeRegistry(): AssetRegistry {
|
|
45
|
+
return new AssetRegistry(makeMockShaderRegistry());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const MESH_PAYLOAD_A = {
|
|
49
|
+
vertices: [
|
|
50
|
+
-0.5, 0, 0.5, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0.5, 0, 0.5, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0.5, 0, -0.5,
|
|
51
|
+
0, 1, 0, 1, 1, 1, 0, 0, 1,
|
|
52
|
+
],
|
|
53
|
+
indices: [0, 1, 2],
|
|
54
|
+
attributes: {},
|
|
55
|
+
submeshes: [{ indexOffset: 0, indexCount: 3, vertexCount: 3, topology: 'triangle-list' }],
|
|
56
|
+
};
|
|
57
|
+
const MESH_PAYLOAD_B = {
|
|
58
|
+
vertices: [
|
|
59
|
+
0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
|
|
60
|
+
1, 1, 0, 0,
|
|
61
|
+
],
|
|
62
|
+
indices: [1, 0, 2],
|
|
63
|
+
attributes: {},
|
|
64
|
+
submeshes: [{ indexOffset: 0, indexCount: 3, vertexCount: 3, topology: 'triangle-list' }],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function makeSharedPack(): unknown {
|
|
68
|
+
return {
|
|
69
|
+
schemaVersion: '2.0.0',
|
|
70
|
+
kind: 'internal-text-package',
|
|
71
|
+
assets: [
|
|
72
|
+
{ guid: MESH_A, kind: 'mesh', payload: MESH_PAYLOAD_A, refs: [], artifacts: {} },
|
|
73
|
+
{ guid: MESH_B, kind: 'mesh', payload: MESH_PAYLOAD_B, refs: [], artifacts: {} },
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const TEX_METADATA = {
|
|
79
|
+
kind: 'texture',
|
|
80
|
+
width: 1,
|
|
81
|
+
height: 1,
|
|
82
|
+
format: 'rgba8unorm',
|
|
83
|
+
colorSpace: 'srgb',
|
|
84
|
+
mipmap: false,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// `includeNames=false` is the FALSIFY variant (entry.name stripped).
|
|
88
|
+
function makePackIndex(includeNames: boolean): unknown[] {
|
|
89
|
+
const named = (n: string) => (includeNames ? { name: n } : {});
|
|
90
|
+
return [
|
|
91
|
+
{
|
|
92
|
+
guid: MESH_A,
|
|
93
|
+
packageUrl: SHARED_PACK_URL,
|
|
94
|
+
kind: 'mesh',
|
|
95
|
+
sourcePath: 'char.glb',
|
|
96
|
+
...named('Body'),
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
guid: MESH_B,
|
|
100
|
+
packageUrl: SHARED_PACK_URL,
|
|
101
|
+
kind: 'mesh',
|
|
102
|
+
sourcePath: 'char.glb',
|
|
103
|
+
...named('Head'),
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
guid: TEX,
|
|
107
|
+
packageUrl: TEX_URL,
|
|
108
|
+
kind: 'texture',
|
|
109
|
+
sourcePath: 'diffuse.png',
|
|
110
|
+
...named('Diffuse'),
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Roundtrip every fetched body through JSON.stringify -> JSON.parse, mirroring
|
|
116
|
+
// the dev-server pack-body transport that dawn smoke skips.
|
|
117
|
+
function jsonRoundtrip(value: unknown): unknown {
|
|
118
|
+
return JSON.parse(JSON.stringify(value));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function installFetch(includeNames: boolean): void {
|
|
122
|
+
const packIndex = jsonRoundtrip(makePackIndex(includeNames));
|
|
123
|
+
const sharedPack = jsonRoundtrip(makeSharedPack());
|
|
124
|
+
const texBytes = new Uint8Array(1 * 1 * 4).fill(200);
|
|
125
|
+
globalThis.fetch = vi.fn(async (url: string | URL) => {
|
|
126
|
+
const u = String(url);
|
|
127
|
+
if (u.includes('pack-index.json')) {
|
|
128
|
+
return new Response(JSON.stringify(packIndex), { status: 200 });
|
|
129
|
+
}
|
|
130
|
+
if (u === SHARED_PACK_URL) {
|
|
131
|
+
return new Response(JSON.stringify(sharedPack), { status: 200 });
|
|
132
|
+
}
|
|
133
|
+
if (u === TEX_URL) {
|
|
134
|
+
return new Response(
|
|
135
|
+
JSON.stringify({
|
|
136
|
+
schemaVersion: '2.0.0',
|
|
137
|
+
kind: 'internal-text-package',
|
|
138
|
+
assets: [
|
|
139
|
+
{
|
|
140
|
+
guid: TEX,
|
|
141
|
+
kind: 'texture',
|
|
142
|
+
payload: TEX_METADATA,
|
|
143
|
+
refs: [],
|
|
144
|
+
artifacts: {
|
|
145
|
+
body: { path: 'diffuse.bin', mediaType: 'application/x-forgeax-rgba8' },
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
}),
|
|
150
|
+
{ status: 200 },
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
if (u === '/assets/diffuse.bin') {
|
|
154
|
+
return new Response(texBytes, { status: 200 });
|
|
155
|
+
}
|
|
156
|
+
return new Response('', { status: 404 });
|
|
157
|
+
}) as unknown as typeof globalThis.fetch;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
describe('loader name survival (AC-08)', () => {
|
|
161
|
+
let originalFetch: typeof globalThis.fetch | undefined;
|
|
162
|
+
beforeEach(() => {
|
|
163
|
+
originalFetch = globalThis.fetch;
|
|
164
|
+
});
|
|
165
|
+
afterEach(() => {
|
|
166
|
+
if (originalFetch !== undefined) globalThis.fetch = originalFetch;
|
|
167
|
+
vi.restoreAllMocks();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('sync branch: multi-asset mesh names survive the JSON roundtrip', async () => {
|
|
171
|
+
installFetch(true);
|
|
172
|
+
const reg = makeRegistry();
|
|
173
|
+
reg.configurePackIndex('/pack-index.json');
|
|
174
|
+
|
|
175
|
+
const rA = await reg.loadByGuid<TypesMeshAsset>(parseGuid(MESH_A));
|
|
176
|
+
const rB = await reg.loadByGuid<TypesMeshAsset>(parseGuid(MESH_B));
|
|
177
|
+
expect(rA.ok).toBe(true);
|
|
178
|
+
expect(rB.ok).toBe(true);
|
|
179
|
+
|
|
180
|
+
expect(reg.resolveName(MESH_A)).toBe('Body');
|
|
181
|
+
expect(reg.resolveName(MESH_B)).toBe('Head');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('async branch: texture package resolves via the async load path post-roundtrip', async () => {
|
|
185
|
+
installFetch(true);
|
|
186
|
+
const reg = makeRegistry();
|
|
187
|
+
reg.configurePackIndex('/pack-index.json');
|
|
188
|
+
|
|
189
|
+
const r = await reg.loadByGuid(parseGuid(TEX));
|
|
190
|
+
expect(r.ok).toBe(true);
|
|
191
|
+
// Single-asset texture package -> basename(path) (AC-01). The wiring is what
|
|
192
|
+
// makes this non-empty: without entry -> Package the texture lands in a null
|
|
193
|
+
// package and resolveName would be ''.
|
|
194
|
+
expect(reg.resolveName(TEX)).toBe('diffuse.pack.json');
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('FALSIFY: stripped entry.name degrades to basename, proving name-sensitivity', async () => {
|
|
198
|
+
installFetch(false);
|
|
199
|
+
const reg = makeRegistry();
|
|
200
|
+
reg.configurePackIndex('/pack-index.json');
|
|
201
|
+
|
|
202
|
+
const rA = await reg.loadByGuid<TypesMeshAsset>(parseGuid(MESH_A));
|
|
203
|
+
const rB = await reg.loadByGuid<TypesMeshAsset>(parseGuid(MESH_B));
|
|
204
|
+
expect(rA.ok).toBe(true);
|
|
205
|
+
expect(rB.ok).toBe(true);
|
|
206
|
+
|
|
207
|
+
// Multi-asset package with no stored names -> basename(cooked packageUrl),
|
|
208
|
+
// NOT the original 'Body' / 'Head'. If the assertion still
|
|
209
|
+
// saw 'Body', the name path would be a tautology.
|
|
210
|
+
expect(reg.resolveName(MESH_A)).toBe('char.pack.json');
|
|
211
|
+
expect(reg.resolveName(MESH_B)).toBe('char.pack.json');
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
// unused-directive error and turn this file red.
|
|
12
12
|
|
|
13
13
|
import { World } from '@forgeax/engine-ecs';
|
|
14
|
-
import {
|
|
15
|
-
import { Camera } from '@forgeax/engine-render/internal';
|
|
14
|
+
import { Camera } from '@forgeax/engine-render';
|
|
16
15
|
import { describe, it } from 'vitest';
|
|
16
|
+
import { GlyphText } from '../../../render/src/components/glyph-text';
|
|
17
|
+
import { Tilemap } from '../../../render/src/components/tilemap';
|
|
17
18
|
|
|
18
19
|
describe('w12 -- residual per-axis M3 keys are compile errors (AC-04)', () => {
|
|
19
20
|
it('Camera rejects residual clearR at spawn call-site', () => {
|