@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
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// feat-20260707-engine-world-clone-transient-for-editor-ssot M3 / m3t2:
|
|
2
|
+
// Transient runtime behavior test (AC-07).
|
|
3
|
+
//
|
|
4
|
+
// AC-07: transient components remain fully functional at runtime despite
|
|
5
|
+
// being skipped by collect. Design doc §6.6 semantic boundary:
|
|
6
|
+
// "transient only affects rootsToSceneAsset write step — not runtime presence."
|
|
7
|
+
//
|
|
8
|
+
// Scenarios:
|
|
9
|
+
// (a) After rootsToSceneAsset runs on a world with Children (transient: true):
|
|
10
|
+
// world.get(entity, Children) returns ok with Children data.
|
|
11
|
+
// (b) query with Children in the query set still matches the entity after collect.
|
|
12
|
+
// (c) world.get(entity, SceneInstance) returns ok after collect.
|
|
13
|
+
// (d) Collect is non-mutating: world.get entity Children before/after collect
|
|
14
|
+
// returns the same value.
|
|
15
|
+
// (e) InstantiateScene on SceneAsset without Children data → mirror hook
|
|
16
|
+
// populates Children correctly for parent entity.
|
|
17
|
+
//
|
|
18
|
+
// Depends on m2t4 (deferred ChildOf wiring) — ChildOf hierarchy is the
|
|
19
|
+
// canonical cause of Children being populated by the mirror hook.
|
|
20
|
+
|
|
21
|
+
import type { Asset } from '@forgeax/engine-assets-runtime';
|
|
22
|
+
import { AssetRegistry } from '@forgeax/engine-assets-runtime';
|
|
23
|
+
import { type EntityHandle, World } from '@forgeax/engine-ecs';
|
|
24
|
+
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
25
|
+
import { SceneInstance } from '@forgeax/engine-render';
|
|
26
|
+
import { ChildOf, Children, Transform } from '@forgeax/engine-scene';
|
|
27
|
+
import type { Handle, LocalEntityId, SceneAsset } from '@forgeax/engine-types';
|
|
28
|
+
import { describe, expect, it } from 'vitest';
|
|
29
|
+
import { rootsToSceneAsset } from '../collect-scene-asset';
|
|
30
|
+
import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
|
|
31
|
+
|
|
32
|
+
function makeRegistry(): AssetRegistry {
|
|
33
|
+
return new AssetRegistry(makeMockShaderRegistry());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function makeWorld(): World {
|
|
37
|
+
const world = new World();
|
|
38
|
+
for (const component of [Transform, ChildOf, Children, SceneInstance]) {
|
|
39
|
+
world.components.register(component).unwrap();
|
|
40
|
+
}
|
|
41
|
+
return world;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function localId(n: number): LocalEntityId {
|
|
45
|
+
return n as LocalEntityId;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function cat(reg: AssetRegistry, g: string, p: SceneAsset): void {
|
|
49
|
+
const r = AssetGuid.parse(g);
|
|
50
|
+
if (!r.ok) throw new Error(`bad GUID: ${g}`);
|
|
51
|
+
reg.catalog(r.value, p as Asset);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function rs(w: World, a: SceneAsset): Handle<'SceneAsset', 'shared'> {
|
|
55
|
+
return w.allocSharedRef('SceneAsset', a);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
describe('m3t2 — transient runtime behavior (AC-07)', () => {
|
|
59
|
+
it('(a) world.get Children ok after rootsToSceneAsset', () => {
|
|
60
|
+
const world = makeWorld();
|
|
61
|
+
const reg = makeRegistry();
|
|
62
|
+
|
|
63
|
+
// Build a hierarchy: parent -> child via ChildOf. Mirror hook populates Children.
|
|
64
|
+
const parent = world.spawn({ component: Transform, data: {} }).unwrap();
|
|
65
|
+
world
|
|
66
|
+
.spawn({ component: Transform, data: {} }, { component: ChildOf, data: { parent } })
|
|
67
|
+
.unwrap();
|
|
68
|
+
|
|
69
|
+
// Children should be populated by mirror hook
|
|
70
|
+
const preChildren = world.get(parent, Children);
|
|
71
|
+
expect(preChildren.ok).toBe(true);
|
|
72
|
+
|
|
73
|
+
// Collect an unrelated scene — this exercises the collect path but never
|
|
74
|
+
// touches the manually-spawned entity
|
|
75
|
+
const asset: SceneAsset = {
|
|
76
|
+
kind: 'scene',
|
|
77
|
+
entities: [{ localId: localId(0), components: {} }],
|
|
78
|
+
};
|
|
79
|
+
cat(reg, '00000000-0000-4000-8000-000000000000', asset);
|
|
80
|
+
const inst = reg.instantiate(rs(world, asset), world);
|
|
81
|
+
expect(inst.ok).toBe(true);
|
|
82
|
+
if (!inst.ok) return;
|
|
83
|
+
|
|
84
|
+
const collected = rootsToSceneAsset(reg, world, [inst.value]);
|
|
85
|
+
expect(collected.ok).toBe(true);
|
|
86
|
+
|
|
87
|
+
// After collect, Children is STILL in the archetype — transient means skip
|
|
88
|
+
// during serialization, not removal from the live world
|
|
89
|
+
const postChildren = world.get(parent, Children);
|
|
90
|
+
expect(postChildren.ok).toBe(true);
|
|
91
|
+
if (!postChildren.ok) return;
|
|
92
|
+
const entities = postChildren.value.entities;
|
|
93
|
+
expect(entities).toBeDefined();
|
|
94
|
+
expect(entities.length).toBeGreaterThanOrEqual(1);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('(b) query with Children still matches entity after collect', () => {
|
|
98
|
+
const world = makeWorld();
|
|
99
|
+
const reg = makeRegistry();
|
|
100
|
+
|
|
101
|
+
const parent = world.spawn({ component: Transform, data: {} }).unwrap();
|
|
102
|
+
world
|
|
103
|
+
.spawn({ component: Transform, data: {} }, { component: ChildOf, data: { parent } })
|
|
104
|
+
.unwrap();
|
|
105
|
+
|
|
106
|
+
// Verify Children is present before collect
|
|
107
|
+
const preChildren = world.get(parent, Children);
|
|
108
|
+
expect(preChildren.ok).toBe(true);
|
|
109
|
+
if (!preChildren.ok) return;
|
|
110
|
+
expect(preChildren.value.entities.length).toBeGreaterThanOrEqual(1);
|
|
111
|
+
|
|
112
|
+
// Collect an unrelated scene to exercise the collect code path
|
|
113
|
+
const asset: SceneAsset = {
|
|
114
|
+
kind: 'scene',
|
|
115
|
+
entities: [{ localId: localId(0), components: {} }],
|
|
116
|
+
};
|
|
117
|
+
cat(reg, '11111111-1111-4111-8111-111111111111', asset);
|
|
118
|
+
const inst = reg.instantiate(rs(world, asset), world);
|
|
119
|
+
expect(inst.ok).toBe(true);
|
|
120
|
+
if (!inst.ok) return;
|
|
121
|
+
rootsToSceneAsset(reg, world, [inst.value]);
|
|
122
|
+
|
|
123
|
+
// After collect, query including Children should still match the parent entity.
|
|
124
|
+
// Include Entity in the `with` list to count matched rows.
|
|
125
|
+
const query = world.query({ with: [Children] }).unwrap();
|
|
126
|
+
let matchedCount = 0;
|
|
127
|
+
for (const _row of query) matchedCount += 1;
|
|
128
|
+
expect(matchedCount).toBeGreaterThanOrEqual(1);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('(c) world.get SceneInstance ok after collect', () => {
|
|
132
|
+
const world = makeWorld();
|
|
133
|
+
const reg = makeRegistry();
|
|
134
|
+
|
|
135
|
+
const child: SceneAsset = {
|
|
136
|
+
kind: 'scene',
|
|
137
|
+
entities: [{ localId: localId(0), components: {} }],
|
|
138
|
+
};
|
|
139
|
+
cat(reg, '22222222-2222-4222-8222-222222222222', child);
|
|
140
|
+
const inst = reg.instantiate(rs(world, child), world);
|
|
141
|
+
expect(inst.ok).toBe(true);
|
|
142
|
+
if (!inst.ok) return;
|
|
143
|
+
|
|
144
|
+
// pre-collect: SceneInstance is present
|
|
145
|
+
const preSI = world.get(inst.value, SceneInstance);
|
|
146
|
+
expect(preSI.ok).toBe(true);
|
|
147
|
+
|
|
148
|
+
// Collect the same root
|
|
149
|
+
const collected = rootsToSceneAsset(reg, world, [inst.value]);
|
|
150
|
+
expect(collected.ok).toBe(true);
|
|
151
|
+
|
|
152
|
+
// post-collect: SceneInstance is still present (it's transient, not removed)
|
|
153
|
+
const postSI = world.get(inst.value, SceneInstance);
|
|
154
|
+
expect(postSI.ok).toBe(true);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('(d) collect is non-mutating: Children pre/post equals', () => {
|
|
158
|
+
const world = makeWorld();
|
|
159
|
+
const reg = makeRegistry();
|
|
160
|
+
|
|
161
|
+
const parent = world.spawn({ component: Transform, data: {} }).unwrap();
|
|
162
|
+
world
|
|
163
|
+
.spawn({ component: Transform, data: {} }, { component: ChildOf, data: { parent } })
|
|
164
|
+
.unwrap();
|
|
165
|
+
|
|
166
|
+
const preChildren = world.get(parent, Children);
|
|
167
|
+
expect(preChildren.ok).toBe(true);
|
|
168
|
+
if (!preChildren.ok) return;
|
|
169
|
+
const preLength = preChildren.value.entities.length;
|
|
170
|
+
|
|
171
|
+
// Collect an unrelated scene
|
|
172
|
+
const asset: SceneAsset = {
|
|
173
|
+
kind: 'scene',
|
|
174
|
+
entities: [{ localId: localId(0), components: {} }],
|
|
175
|
+
};
|
|
176
|
+
cat(reg, '33333333-3333-4333-8333-333333333333', asset);
|
|
177
|
+
const inst = reg.instantiate(rs(world, asset), world);
|
|
178
|
+
expect(inst.ok).toBe(true);
|
|
179
|
+
if (!inst.ok) return;
|
|
180
|
+
rootsToSceneAsset(reg, world, [inst.value]);
|
|
181
|
+
|
|
182
|
+
const postChildren = world.get(parent, Children);
|
|
183
|
+
expect(postChildren.ok).toBe(true);
|
|
184
|
+
if (!postChildren.ok) return;
|
|
185
|
+
// children count unchanged (collect does not mutate the world)
|
|
186
|
+
expect(postChildren.value.entities.length).toBe(preLength);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('(e) instantiateScene of Children-absent SceneAsset → mirror hook populates Children', () => {
|
|
190
|
+
const world = makeWorld();
|
|
191
|
+
const reg = makeRegistry();
|
|
192
|
+
|
|
193
|
+
// Build a minimal SceneAsset: parent entity at localId 0 + child entity at
|
|
194
|
+
// localId 1 with ChildOf pointing to localId 0. No Children data in the asset.
|
|
195
|
+
// The mirror hook should populate Children on entity at localId 0.
|
|
196
|
+
const asset: SceneAsset = {
|
|
197
|
+
kind: 'scene',
|
|
198
|
+
entities: [
|
|
199
|
+
{ localId: localId(0), components: { Transform: {} } },
|
|
200
|
+
{ localId: localId(1), components: { Transform: {}, ChildOf: { parent: localId(0) } } },
|
|
201
|
+
],
|
|
202
|
+
};
|
|
203
|
+
cat(reg, '44444444-4444-4444-8444-444444444444', asset);
|
|
204
|
+
const inst = reg.instantiate(rs(world, asset), world);
|
|
205
|
+
expect(inst.ok).toBe(true);
|
|
206
|
+
if (!inst.ok) return;
|
|
207
|
+
|
|
208
|
+
// The root entity carries SceneInstance with mapping array
|
|
209
|
+
const siR = world.get(inst.value, SceneInstance);
|
|
210
|
+
expect(siR.ok).toBe(true);
|
|
211
|
+
if (!siR.ok) return;
|
|
212
|
+
const mapping = siR.value.mapping;
|
|
213
|
+
expect(mapping).toBeDefined();
|
|
214
|
+
|
|
215
|
+
// mapping[0] is the entity at localId 0 (the parent). Entity handle 0
|
|
216
|
+
// is a valid entity in forgeax (ENTITY_NULL_RAW = 0xFFFFFFFF, not 0).
|
|
217
|
+
const parentEntity = mapping[0] as unknown as EntityHandle;
|
|
218
|
+
|
|
219
|
+
// The mirror hook should have populated Children on the parent entity
|
|
220
|
+
// because entity at localId 1 has ChildOf{parent = localId 0}
|
|
221
|
+
const cr = world.get(parentEntity, Children);
|
|
222
|
+
expect(cr.ok).toBe(true);
|
|
223
|
+
if (!cr.ok) return;
|
|
224
|
+
const ents = cr.value.entities;
|
|
225
|
+
expect(ents.length).toBeGreaterThanOrEqual(1);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
// occlude them).
|
|
28
28
|
|
|
29
29
|
import { World } from '@forgeax/engine-ecs';
|
|
30
|
-
import
|
|
30
|
+
import { describe, expect, it } from 'vitest';
|
|
31
|
+
import type { TransparentEntry } from '../../../render/src/systems/transparent-sort-config';
|
|
31
32
|
import {
|
|
32
|
-
effectivePivotYForTilemapFlip,
|
|
33
33
|
setTransparentSortConfig,
|
|
34
34
|
TRANSPARENT_SORT_MODE_LAYER_Y,
|
|
35
|
-
} from '
|
|
36
|
-
import {
|
|
35
|
+
} from '../../../render/src/systems/transparent-sort-config';
|
|
36
|
+
import { effectivePivotYForTilemapFlip } from '../../../render/src/tilemap-chunk-extract-system';
|
|
37
37
|
import { transparentSortEntries } from '../systems/transparent-sort';
|
|
38
38
|
|
|
39
39
|
const FALSIFY = process.env.FORGEAX_FALSIFY_TILEMAP_SORT;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { variantSetFromDefines } from '@forgeax/engine-render/internal';
|
|
2
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { variantSetFromDefines } from '../../../render/src/record/helpers';
|
|
3
3
|
|
|
4
4
|
describe('material pass variant selection', () => {
|
|
5
5
|
it('uses the manifest key order without mutating the pass map', () => {
|
|
@@ -27,20 +27,12 @@
|
|
|
27
27
|
// the per-frame upload itself lands in w16, here the field falls back to the
|
|
28
28
|
// default view until a frame is uploaded).
|
|
29
29
|
|
|
30
|
+
import { AssetRegistry, HANDLE_CUBE, HANDLE_QUAD } from '@forgeax/engine-assets-runtime';
|
|
30
31
|
import { World } from '@forgeax/engine-ecs';
|
|
31
|
-
import { createPlaneGeometry } from '@forgeax/engine-geometry';
|
|
32
32
|
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
33
|
-
import {
|
|
34
|
-
Camera,
|
|
35
|
-
extractFrame,
|
|
36
|
-
MeshFilter,
|
|
37
|
-
MeshRenderer,
|
|
38
|
-
prepareExtractContext,
|
|
39
|
-
type RenderAssetPort,
|
|
40
|
-
} from '@forgeax/engine-render/internal';
|
|
33
|
+
import { Camera, MeshFilter, MeshRenderer } from '@forgeax/engine-render';
|
|
41
34
|
import { propagateTransforms, Transform } from '@forgeax/engine-scene';
|
|
42
35
|
import type {
|
|
43
|
-
Asset,
|
|
44
36
|
Handle,
|
|
45
37
|
MaterialAsset,
|
|
46
38
|
MaterialPass,
|
|
@@ -48,7 +40,13 @@ import type {
|
|
|
48
40
|
VideoAsset,
|
|
49
41
|
} from '@forgeax/engine-types';
|
|
50
42
|
import { describe, expect, it } from 'vitest';
|
|
51
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
Camera as SourceCamera,
|
|
45
|
+
MeshFilter as SourceMeshFilter,
|
|
46
|
+
MeshRenderer as SourceMeshRenderer,
|
|
47
|
+
} from '../../../render/src/components';
|
|
48
|
+
import { extractFrame, prepareExtractContext } from '../../../render/src/render-system-extract';
|
|
49
|
+
import { constructRuntimeRendererHost } from '../renderer-host';
|
|
52
50
|
import { drawPublished } from './draw-published';
|
|
53
51
|
import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
|
|
54
52
|
|
|
@@ -72,63 +70,21 @@ function transformData(x: number, y: number, z: number) {
|
|
|
72
70
|
}
|
|
73
71
|
|
|
74
72
|
function registerTestMesh(world: World) {
|
|
75
|
-
const mesh =
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
readonly port: RenderAssetPort;
|
|
82
|
-
readonly resolver: {
|
|
83
|
-
readonly epoch: number;
|
|
84
|
-
lookup<T extends Asset>(guid: string): T | undefined;
|
|
85
|
-
guidOf(asset: Asset): string | undefined;
|
|
86
|
-
};
|
|
87
|
-
publish(guid: string | AssetGuid, asset: Asset): void;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function createTestAssetStore(): TestAssetStore {
|
|
91
|
-
const shaderRegistry = makeMockShaderRegistry();
|
|
92
|
-
const payloads = new Map<string, Asset>();
|
|
93
|
-
const guids = new WeakMap<object, string>();
|
|
94
|
-
let epoch = 0;
|
|
95
|
-
const keyOf = (guid: string): string => guid.toLowerCase().replaceAll('-', '');
|
|
96
|
-
const resolver = {
|
|
97
|
-
get epoch() {
|
|
98
|
-
return epoch;
|
|
99
|
-
},
|
|
100
|
-
lookup<T extends Asset>(guid: string): T | undefined {
|
|
101
|
-
return payloads.get(keyOf(guid)) as T | undefined;
|
|
102
|
-
},
|
|
103
|
-
guidOf(asset: Asset): string | undefined {
|
|
104
|
-
return guids.get(asset);
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
const port: RenderAssetPort = {
|
|
108
|
-
get epoch() {
|
|
109
|
-
return resolver.epoch;
|
|
110
|
-
},
|
|
111
|
-
shaderRegistry,
|
|
112
|
-
lookup: resolver.lookup,
|
|
113
|
-
guidOf: resolver.guidOf,
|
|
114
|
-
materialShaderTextureFieldNames(shaderId: string): readonly string[] {
|
|
115
|
-
const artifact = shaderRegistry.findMaterialArtifact(shaderId);
|
|
116
|
-
if (!artifact.ok) return [];
|
|
117
|
-
return artifact.value.paramSchema
|
|
118
|
-
.filter((parameter) => parameter.type === 'texture2d')
|
|
119
|
-
.map((parameter) => parameter.name);
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
return {
|
|
123
|
-
port,
|
|
124
|
-
resolver,
|
|
125
|
-
publish(guid, asset) {
|
|
126
|
-
const formatted = typeof guid === 'string' ? guid : AssetGuid.format(guid);
|
|
127
|
-
payloads.set(keyOf(formatted), asset);
|
|
128
|
-
guids.set(asset, formatted);
|
|
129
|
-
epoch += 1;
|
|
73
|
+
const mesh: MeshAsset = {
|
|
74
|
+
kind: 'mesh',
|
|
75
|
+
vertices: new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]),
|
|
76
|
+
indices: new Uint16Array([0, 1, 2]),
|
|
77
|
+
attributes: {
|
|
78
|
+
position: new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]),
|
|
130
79
|
},
|
|
80
|
+
aabb: new Float32Array([0, 0, 0, 1, 1, 1]),
|
|
81
|
+
submeshes: [
|
|
82
|
+
{ indexOffset: 0, indexCount: 3, vertexCount: 3, topology: 'triangle-list', materialSlot: 0 },
|
|
83
|
+
],
|
|
84
|
+
|
|
85
|
+
materialSlots: [{ slotName: 'Default' }],
|
|
131
86
|
};
|
|
87
|
+
return world.allocSharedRef<'MeshAsset', MeshAsset>('MeshAsset', mesh);
|
|
132
88
|
}
|
|
133
89
|
|
|
134
90
|
/**
|
|
@@ -137,29 +93,19 @@ function createTestAssetStore(): TestAssetStore {
|
|
|
137
93
|
*/
|
|
138
94
|
function catalogVideoMaterial(
|
|
139
95
|
world: World,
|
|
140
|
-
assets:
|
|
96
|
+
assets: AssetRegistry,
|
|
141
97
|
): { matHandle: Handle<'MaterialAsset', 'shared'>; videoGuid: AssetGuid } {
|
|
142
98
|
const videoGuid = AssetGuid.random();
|
|
143
99
|
const videoGuidStr = AssetGuid.format(videoGuid);
|
|
144
100
|
const video: VideoAsset = { kind: 'video', url: 'extract-bindgroup-clip.webm' };
|
|
145
|
-
assets.
|
|
101
|
+
assets.catalog(videoGuid, video);
|
|
146
102
|
|
|
147
103
|
const material: MaterialAsset = {
|
|
148
104
|
kind: 'material',
|
|
149
105
|
passes: [FORWARD_PBR_PASS],
|
|
150
106
|
// The video GUID occupies the baseColorTexture texture2d slot — exactly the
|
|
151
107
|
// shape a static texture would (D-5 reuse of the texture2d slot).
|
|
152
|
-
values: {
|
|
153
|
-
baseColor: [1, 1, 1],
|
|
154
|
-
baseColorTexture: {
|
|
155
|
-
texture: videoGuidStr as never,
|
|
156
|
-
coordinates: {
|
|
157
|
-
set: 0,
|
|
158
|
-
transform: { offset: [0, 0], scale: [1, 1], rotation: 0 },
|
|
159
|
-
physicalUvScale: [1, 1],
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
},
|
|
108
|
+
values: { baseColor: [1, 1, 1], baseColorTexture: { texture: videoGuidStr as never } },
|
|
163
109
|
} as MaterialAsset;
|
|
164
110
|
const matHandle = world.allocSharedRef<'MaterialAsset', MaterialAsset>('MaterialAsset', material);
|
|
165
111
|
return { matHandle, videoGuid };
|
|
@@ -167,33 +113,34 @@ function catalogVideoMaterial(
|
|
|
167
113
|
|
|
168
114
|
describe('AC-06 / R-7 — video GUID in values is a recognised texture field (M4 / w13)', () => {
|
|
169
115
|
it('R-7: baseColorTexture is in the standard-PBR shader textureFieldNames set', () => {
|
|
170
|
-
const assets =
|
|
171
|
-
const fields = assets.
|
|
172
|
-
expect(fields).
|
|
116
|
+
const assets = new AssetRegistry(makeMockShaderRegistry());
|
|
117
|
+
const fields = assets.materialShaderTextureFieldNames(STANDARD_PBR_SHADER);
|
|
118
|
+
expect(fields, 'standard-PBR shader must declare texture fields').toBeDefined();
|
|
119
|
+
expect(fields?.has('baseColorTexture')).toBe(true);
|
|
173
120
|
});
|
|
174
121
|
|
|
175
122
|
it('extract flags the video-sourced field and does NOT carry it as a static TextureAsset handle', () => {
|
|
176
123
|
const world = new World();
|
|
177
|
-
const assets =
|
|
124
|
+
const assets = new AssetRegistry(makeMockShaderRegistry());
|
|
178
125
|
const mesh = registerTestMesh(world);
|
|
179
126
|
const { matHandle } = catalogVideoMaterial(world, assets);
|
|
180
127
|
|
|
181
128
|
world
|
|
182
129
|
.spawn(
|
|
183
|
-
{ component: Transform, data: transformData(0, 0,
|
|
184
|
-
{ component:
|
|
185
|
-
{ component: MeshRenderer, data: { materials: [matHandle] } },
|
|
130
|
+
{ component: Transform, data: transformData(0, 0, 5) },
|
|
131
|
+
{ component: SourceCamera, data: { fov: Math.PI / 4, aspect: 1, near: 0.1, far: 100 } },
|
|
186
132
|
)
|
|
187
133
|
.unwrap();
|
|
188
134
|
world
|
|
189
135
|
.spawn(
|
|
190
|
-
{ component: Transform, data: transformData(0, 0,
|
|
191
|
-
{ component:
|
|
136
|
+
{ component: Transform, data: transformData(0, 0, 0) },
|
|
137
|
+
{ component: SourceMeshFilter, data: { assetHandle: mesh } },
|
|
138
|
+
{ component: SourceMeshRenderer, data: { materials: [matHandle] } },
|
|
192
139
|
)
|
|
193
140
|
.unwrap();
|
|
194
141
|
|
|
195
142
|
propagateTransforms(world);
|
|
196
|
-
const frame = extractFrame(world, prepareExtractContext(world, { assets:
|
|
143
|
+
const frame = extractFrame(world, prepareExtractContext(world, { assets, cull: 'none' }));
|
|
197
144
|
expect(frame.renderables.length).toBe(1);
|
|
198
145
|
const mat = frame.renderables[0]?.material;
|
|
199
146
|
expect(mat).toBeDefined();
|
|
@@ -209,7 +156,8 @@ describe('AC-06 / R-7 — video GUID in values is a recognised texture field (M4
|
|
|
209
156
|
});
|
|
210
157
|
|
|
211
158
|
interface DawnHarness {
|
|
212
|
-
renderer:
|
|
159
|
+
renderer: import('@forgeax/engine-render').Renderer;
|
|
160
|
+
assets: AssetRegistry;
|
|
213
161
|
device: GPUDevice;
|
|
214
162
|
}
|
|
215
163
|
|
|
@@ -221,7 +169,7 @@ const ENGINE_MANIFEST_URL = `data:application/json,${encodeURIComponent(
|
|
|
221
169
|
JSON.stringify(ENGINE_MANIFEST),
|
|
222
170
|
)}`;
|
|
223
171
|
|
|
224
|
-
async function bootDawn(
|
|
172
|
+
async function bootDawn(): Promise<DawnHarness | null> {
|
|
225
173
|
const dawnAvailable = typeof globalThis.navigator?.gpu?.requestAdapter === 'function';
|
|
226
174
|
if (!dawnAvailable) {
|
|
227
175
|
throw new Error('dawn-node navigator.gpu not injected; vitest.setup-webgpu.ts regressed');
|
|
@@ -278,64 +226,65 @@ async function bootDawn(assetStore: TestAssetStore): Promise<DawnHarness | null>
|
|
|
278
226
|
removeEventListener() {},
|
|
279
227
|
} as unknown as HTMLCanvasElement;
|
|
280
228
|
|
|
281
|
-
let
|
|
229
|
+
let host: Awaited<ReturnType<typeof constructRuntimeRendererHost>>;
|
|
282
230
|
try {
|
|
283
|
-
|
|
231
|
+
host = await constructRuntimeRendererHost(
|
|
284
232
|
mockCanvas,
|
|
285
233
|
{},
|
|
286
|
-
{
|
|
234
|
+
{
|
|
235
|
+
shaderManifestUrl: ENGINE_MANIFEST_URL,
|
|
236
|
+
},
|
|
287
237
|
);
|
|
288
238
|
} finally {
|
|
289
239
|
globalThis.navigator.gpu.requestAdapter = originalRequestAdapter;
|
|
290
240
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
241
|
+
expect(host.ok).toBe(true);
|
|
242
|
+
if (!host.ok) throw host.error;
|
|
243
|
+
const { renderer, assets } = host.value;
|
|
244
|
+
expect(renderer.inspect().state).toBe('alive');
|
|
294
245
|
if (sharedDevice === undefined) throw new Error('dawn device never captured');
|
|
295
246
|
ensureRenderTarget(sharedDevice, 'rgba8unorm');
|
|
296
|
-
return { renderer, device: sharedDevice };
|
|
247
|
+
return { renderer, assets, device: sharedDevice };
|
|
297
248
|
}
|
|
298
249
|
|
|
299
250
|
describe('AC-06 — extract->record->bind group does not blow up on a video field (dawn) (M4 / w13)', () => {
|
|
300
251
|
it('a renderer frame with a video-sourced baseColorTexture draws with 0 RhiError', async () => {
|
|
301
|
-
const
|
|
302
|
-
const harness = await bootDawn(assetStore);
|
|
252
|
+
const harness = await bootDawn();
|
|
303
253
|
if (harness === null) return;
|
|
304
|
-
const { renderer, device } = harness;
|
|
254
|
+
const { renderer, assets, device } = harness;
|
|
305
255
|
|
|
306
256
|
const videoGuid = AssetGuid.random();
|
|
307
257
|
const videoGuidStr = AssetGuid.format(videoGuid);
|
|
308
258
|
const video: VideoAsset = { kind: 'video', url: 'extract-bindgroup-clip.webm' };
|
|
309
|
-
|
|
259
|
+
const videoCatalog = assets.catalog(videoGuid, video as never);
|
|
260
|
+
expect(videoCatalog.ok).toBe(true);
|
|
310
261
|
|
|
311
262
|
const materialPayload = {
|
|
312
263
|
kind: 'material' as const,
|
|
313
264
|
passes: [FORWARD_PBR_PASS],
|
|
314
265
|
values: {
|
|
315
266
|
baseColor: [1, 1, 1],
|
|
316
|
-
baseColorTexture: {
|
|
317
|
-
texture: videoGuidStr,
|
|
318
|
-
coordinates: {
|
|
319
|
-
set: 0,
|
|
320
|
-
transform: { offset: [0, 0], scale: [1, 1], rotation: 0 },
|
|
321
|
-
physicalUvScale: [1, 1],
|
|
322
|
-
},
|
|
323
|
-
},
|
|
267
|
+
baseColorTexture: { texture: videoGuidStr as never },
|
|
324
268
|
},
|
|
325
269
|
};
|
|
326
270
|
|
|
327
|
-
const errorCodes: string
|
|
328
|
-
const unsub = renderer.
|
|
329
|
-
|
|
271
|
+
const errorCodes: Array<{ code: string; causeCode?: string }> = [];
|
|
272
|
+
const unsub = renderer.subscribe((event) => {
|
|
273
|
+
if (event.kind !== 'error') return;
|
|
274
|
+
errorCodes.push({
|
|
275
|
+
code: event.error.code,
|
|
276
|
+
...(event.error.code === 'device-operation-failed'
|
|
277
|
+
? { causeCode: event.error.detail.cause.code }
|
|
278
|
+
: {}),
|
|
279
|
+
});
|
|
330
280
|
});
|
|
331
281
|
|
|
332
282
|
const world = new World();
|
|
333
|
-
const meshHandle = registerTestMesh(world);
|
|
334
283
|
const matHandle = world.allocSharedRef('MaterialAsset', materialPayload);
|
|
335
284
|
world
|
|
336
285
|
.spawn(
|
|
337
286
|
{ component: Transform, data: transformData(0, 0, 0) },
|
|
338
|
-
{ component: MeshFilter, data: { assetHandle:
|
|
287
|
+
{ component: MeshFilter, data: { assetHandle: HANDLE_CUBE } },
|
|
339
288
|
{ component: MeshRenderer, data: { materials: [matHandle] } },
|
|
340
289
|
)
|
|
341
290
|
.unwrap();
|
|
@@ -355,7 +304,10 @@ describe('AC-06 — extract->record->bind group does not blow up on a video fiel
|
|
|
355
304
|
// (the bind group is well-formed; the field falls back to the default view).
|
|
356
305
|
// The expected, structured `video-upload-unsupported` signal (AC-10, asserted
|
|
357
306
|
// below) is NOT a validation error and is excluded here.
|
|
358
|
-
const validationErrors = errorCodes.filter(
|
|
307
|
+
const validationErrors = errorCodes.filter(
|
|
308
|
+
(event) =>
|
|
309
|
+
event.code !== 'video-upload-unsupported' && event.causeCode !== 'video-upload-unsupported',
|
|
310
|
+
);
|
|
359
311
|
expect(
|
|
360
312
|
validationErrors,
|
|
361
313
|
'a video-sourced texture field must not trip any WebGPU validation error',
|
|
@@ -370,20 +322,19 @@ describe('AC-06 — extract->record->bind group does not blow up on a video fiel
|
|
|
370
322
|
// the production draw path end-to-end, replacing the prior orphan pure-function
|
|
371
323
|
// test (resolveVideoUpload) that the production render path never called.
|
|
372
324
|
it('AC-10: production draw fires video-upload-unsupported on capability double-miss', async () => {
|
|
373
|
-
const
|
|
374
|
-
const harness = await bootDawn(assetStore);
|
|
325
|
+
const harness = await bootDawn();
|
|
375
326
|
if (harness === null) return;
|
|
376
|
-
const { renderer, device } = harness;
|
|
327
|
+
const { renderer, assets, device } = harness;
|
|
377
328
|
|
|
378
329
|
const videoGuid = AssetGuid.random();
|
|
379
330
|
const videoGuidStr = AssetGuid.format(videoGuid);
|
|
380
331
|
const video: VideoAsset = { kind: 'video', url: 'double-miss-clip.webm' };
|
|
381
|
-
|
|
332
|
+
expect(assets.catalog(videoGuid, video as never).ok).toBe(true);
|
|
382
333
|
|
|
383
|
-
// Mirror the demo recipe exactly: unlit shader +
|
|
334
|
+
// Mirror the demo recipe exactly: unlit shader + HANDLE_QUAD. The video
|
|
384
335
|
// upload path (videoTextureView) is reached via the per-submesh user-region
|
|
385
336
|
// bind-group loop, which iterates the shader's textureFieldNames; unlit
|
|
386
|
-
// declares baseColorTexture there. (The earlier standard-PBR
|
|
337
|
+
// declares baseColorTexture there. (The earlier standard-PBR + HANDLE_CUBE
|
|
387
338
|
// shape routes through a different builtin-cube pipeline branch that does not
|
|
388
339
|
// hit the user-region video loop — not the production demo path.)
|
|
389
340
|
const materialPayload = {
|
|
@@ -397,32 +348,31 @@ describe('AC-06 — extract->record->bind group does not blow up on a video fiel
|
|
|
397
348
|
],
|
|
398
349
|
values: {
|
|
399
350
|
baseColor: [1, 1, 1],
|
|
400
|
-
baseColorTexture: {
|
|
401
|
-
texture: videoGuidStr,
|
|
402
|
-
coordinates: {
|
|
403
|
-
set: 0,
|
|
404
|
-
transform: { offset: [0, 0], scale: [1, 1], rotation: 0 },
|
|
405
|
-
physicalUvScale: [1, 1],
|
|
406
|
-
},
|
|
407
|
-
},
|
|
351
|
+
baseColorTexture: { texture: videoGuidStr as never },
|
|
408
352
|
},
|
|
409
353
|
};
|
|
410
354
|
|
|
411
|
-
const fired: { code: string; hint: string }[] = [];
|
|
412
|
-
const unsub = renderer.
|
|
413
|
-
|
|
355
|
+
const fired: { code: string; causeCode?: string; hint: string }[] = [];
|
|
356
|
+
const unsub = renderer.subscribe((event) => {
|
|
357
|
+
if (event.kind !== 'error') return;
|
|
358
|
+
fired.push({
|
|
359
|
+
code: event.error.code,
|
|
360
|
+
...(event.error.code === 'device-operation-failed'
|
|
361
|
+
? { causeCode: event.error.detail.cause.code }
|
|
362
|
+
: {}),
|
|
363
|
+
hint: event.error.hint,
|
|
364
|
+
});
|
|
414
365
|
});
|
|
415
366
|
|
|
416
367
|
const world = new World();
|
|
417
368
|
// NB: NO VIDEO_ELEMENT_PROVIDER_KEY resource inserted -> the production
|
|
418
369
|
// upload path resolves element===undefined; high-perf path is absent on
|
|
419
370
|
// dawn -> genuine AC-10 double-miss.
|
|
420
|
-
const meshHandle = registerTestMesh(world);
|
|
421
371
|
const matHandle = world.allocSharedRef('MaterialAsset', materialPayload);
|
|
422
372
|
world
|
|
423
373
|
.spawn(
|
|
424
374
|
{ component: Transform, data: transformData(0, 0, 0) },
|
|
425
|
-
{ component: MeshFilter, data: { assetHandle:
|
|
375
|
+
{ component: MeshFilter, data: { assetHandle: HANDLE_QUAD } },
|
|
426
376
|
{ component: MeshRenderer, data: { materials: [matHandle] } },
|
|
427
377
|
)
|
|
428
378
|
.unwrap();
|
|
@@ -438,7 +388,10 @@ describe('AC-06 — extract->record->bind group does not blow up on a video fiel
|
|
|
438
388
|
await device.queue.onSubmittedWorkDone();
|
|
439
389
|
if (typeof unsub === 'function') unsub();
|
|
440
390
|
|
|
441
|
-
const unsupported = fired.filter(
|
|
391
|
+
const unsupported = fired.filter(
|
|
392
|
+
(event) =>
|
|
393
|
+
event.code === 'video-upload-unsupported' || event.causeCode === 'video-upload-unsupported',
|
|
394
|
+
);
|
|
442
395
|
expect(
|
|
443
396
|
unsupported.length,
|
|
444
397
|
'production videoTextureView must fire video-upload-unsupported on double-miss (AC-10), not silently bind default',
|