@forgeax/engine-runtime 0.1.4 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -83
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/animation-graph-serialize.unit.test.d.ts +2 -0
- package/dist/__tests__/animation-graph-serialize.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts +2 -0
- package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts.map +1 -0
- package/dist/__tests__/asset-error-exhaustive.test-d.d.ts +11 -0
- package/dist/__tests__/asset-error-exhaustive.test-d.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-guid-reverse.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-guid-reverse.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-mounts.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-mounts.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.browser.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.browser.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.dawn.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.listCatalog.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.listCatalog.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.mesh-bin.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.mesh-bin.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.pack-cache.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.pack-cache.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.recursive.spec.d.ts +2 -0
- package/dist/__tests__/asset-registry.recursive.spec.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.unit.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset.unit.test.d.ts +2 -0
- package/dist/__tests__/asset.unit.test.d.ts.map +1 -0
- package/dist/__tests__/audio-load-by-guid.unit.test.d.ts +2 -0
- package/dist/__tests__/audio-load-by-guid.unit.test.d.ts.map +1 -0
- package/dist/__tests__/backend-selection.integration.test.d.ts +2 -0
- package/dist/__tests__/backend-selection.integration.test.d.ts.map +1 -0
- package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts +2 -0
- package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts.map +1 -0
- package/dist/__tests__/builtin-asset-registry.unit.test.d.ts +2 -0
- package/dist/__tests__/builtin-asset-registry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/collect-scene-asset.test.d.ts +1 -2
- package/dist/__tests__/collect-scene-asset.test.d.ts.map +1 -1
- package/dist/__tests__/collect-scene-mount-collapse.test.d.ts +2 -0
- package/dist/__tests__/collect-scene-mount-collapse.test.d.ts.map +1 -0
- package/dist/__tests__/collect-transient-roundtrip.test.d.ts +1 -1
- package/dist/__tests__/collect-transient-roundtrip.test.d.ts.map +1 -1
- package/dist/__tests__/collect-transient-skip.test.d.ts +1 -2
- package/dist/__tests__/collect-transient-skip.test.d.ts.map +1 -1
- package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts +2 -0
- package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts.map +1 -0
- package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts +2 -0
- package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts.map +1 -0
- package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts +2 -0
- package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/draw-published.d.ts +2 -2
- package/dist/__tests__/draw-published.d.ts.map +1 -1
- package/dist/__tests__/dynamic-texture-store.unit.test.d.ts +2 -0
- package/dist/__tests__/dynamic-texture-store.unit.test.d.ts.map +1 -0
- package/dist/__tests__/errors.unit.test.d.ts +2 -0
- package/dist/__tests__/errors.unit.test.d.ts.map +1 -0
- package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts +2 -0
- package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts.map +1 -0
- package/dist/__tests__/fetch-binary-decompress.test.d.ts +2 -0
- package/dist/__tests__/fetch-binary-decompress.test.d.ts.map +1 -0
- package/dist/__tests__/four-path-compression.integration.test.d.ts +2 -0
- package/dist/__tests__/four-path-compression.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts +2 -0
- package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/guid-for-asset.unit.test.d.ts +2 -0
- package/dist/__tests__/guid-for-asset.unit.test.d.ts.map +1 -0
- package/dist/__tests__/handle-migration.test.d.ts +2 -0
- package/dist/__tests__/handle-migration.test.d.ts.map +1 -0
- package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
- package/dist/__tests__/host-custom-kind-contract.test-d.d.ts +2 -0
- package/dist/__tests__/host-custom-kind-contract.test-d.d.ts.map +1 -0
- package/dist/__tests__/host-custom-kind-contract.test.d.ts +2 -0
- package/dist/__tests__/host-custom-kind-contract.test.d.ts.map +1 -0
- package/dist/__tests__/inspect-name.test.d.ts +2 -0
- package/dist/__tests__/inspect-name.test.d.ts.map +1 -0
- package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts +2 -0
- package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts.map +1 -0
- package/dist/__tests__/loadbyguid-payload.unit.test.d.ts +2 -0
- package/dist/__tests__/loadbyguid-payload.unit.test.d.ts.map +1 -0
- package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts +2 -0
- package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts.map +1 -0
- package/dist/__tests__/loader-extract-graceful.test.d.ts +2 -0
- package/dist/__tests__/loader-extract-graceful.test.d.ts.map +1 -0
- package/dist/__tests__/loader-name-survival.test.d.ts +2 -0
- package/dist/__tests__/loader-name-survival.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin-contract.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin-contract.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/new-kind-refs-contract.test.d.ts +2 -0
- package/dist/__tests__/new-kind-refs-contract.test.d.ts.map +1 -0
- package/dist/__tests__/package-promotion.test.d.ts +2 -0
- package/dist/__tests__/package-promotion.test.d.ts.map +1 -0
- package/dist/__tests__/package-rename.test.d.ts +2 -0
- package/dist/__tests__/package-rename.test.d.ts.map +1 -0
- package/dist/__tests__/recover-error-exhaustive.test-d.d.ts +1 -1
- package/dist/__tests__/recover-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts +1 -1
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts +10 -0
- package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts.map +1 -0
- package/dist/__tests__/render-system-extract.unit.test.d.ts +2 -0
- package/dist/__tests__/render-system-extract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/renderer-test-utils.d.ts +10 -0
- package/dist/__tests__/renderer-test-utils.d.ts.map +1 -0
- package/dist/__tests__/renderer.test-d.d.ts +2 -0
- package/dist/__tests__/renderer.test-d.d.ts.map +1 -0
- package/dist/__tests__/resolve-asset-handle-err.test.d.ts +2 -0
- package/dist/__tests__/resolve-asset-handle-err.test.d.ts.map +1 -0
- package/dist/__tests__/resolve-asset-handle.unit.test.d.ts +2 -0
- package/dist/__tests__/resolve-asset-handle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName-fallback.test.d.ts +2 -0
- package/dist/__tests__/resolveName-fallback.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName-null-package.test.d.ts +2 -0
- package/dist/__tests__/resolveName-null-package.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName-unified-entry.test.d.ts +2 -0
- package/dist/__tests__/resolveName-unified-entry.test.d.ts.map +1 -0
- package/dist/__tests__/resolveName.test.d.ts +2 -0
- package/dist/__tests__/resolveName.test.d.ts.map +1 -0
- package/dist/__tests__/roots-to-scene-asset.test.d.ts +1 -1
- package/dist/__tests__/roots-to-scene-asset.test.d.ts.map +1 -1
- package/dist/__tests__/roundtrip-primitive.test.d.ts +2 -0
- package/dist/__tests__/roundtrip-primitive.test.d.ts.map +1 -0
- package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts +2 -0
- package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts.map +1 -0
- package/dist/__tests__/scene-instance-authoring.integration.test.d.ts +2 -0
- package/dist/__tests__/scene-instance-authoring.integration.test.d.ts.map +1 -0
- package/dist/__tests__/scene-mount-fixed-point.test.d.ts +2 -0
- package/dist/__tests__/scene-mount-fixed-point.test.d.ts.map +1 -0
- package/dist/__tests__/scene-mount-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/scene-mount-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/scene-sugar-instantiate.test.d.ts +2 -0
- package/dist/__tests__/scene-sugar-instantiate.test.d.ts.map +1 -0
- package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/serialize-scene-asset.test.d.ts +1 -1
- package/dist/__tests__/serialize-scene-asset.test.d.ts.map +1 -1
- package/dist/__tests__/template-game-default-api-contract.test.d.ts +2 -0
- package/dist/__tests__/template-game-default-api-contract.test.d.ts.map +1 -0
- package/dist/__tests__/tileset-asset-validate.test.d.ts +2 -0
- package/dist/__tests__/tileset-asset-validate.test.d.ts.map +1 -0
- package/dist/__tests__/transcode-fallback.unit.test.d.ts +2 -0
- package/dist/__tests__/transcode-fallback.unit.test.d.ts.map +1 -0
- package/dist/__tests__/transient-runtime-behavior.test.d.ts +2 -0
- package/dist/__tests__/transient-runtime-behavior.test.d.ts.map +1 -0
- package/dist/__tests__/video-loader-consumption.test.d.ts +2 -0
- package/dist/__tests__/video-loader-consumption.test.d.ts.map +1 -0
- package/dist/__tests__/video-loader-smoke.dawn.test.d.ts +2 -0
- package/dist/__tests__/video-loader-smoke.dawn.test.d.ts.map +1 -0
- package/dist/backend-selection.d.ts +13 -0
- package/dist/backend-selection.d.ts.map +1 -0
- package/dist/collect-scene-asset.d.ts +7 -4
- package/dist/collect-scene-asset.d.ts.map +1 -1
- package/dist/createRenderer.d.ts +14 -2
- package/dist/createRenderer.d.ts.map +1 -1
- package/dist/errors/environment.d.ts +1 -1
- package/dist/errors/environment.d.ts.map +1 -1
- package/dist/index.d.ts +20 -82
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +107 -108
- package/dist/index.mjs.map +1 -1
- package/dist/renderer-host.d.ts +9 -0
- package/dist/renderer-host.d.ts.map +1 -0
- package/dist/renderer-host.mjs +62 -0
- package/dist/renderer-host.mjs.map +1 -0
- package/dist/scene-instances/index.d.ts +2 -0
- package/dist/scene-instances/index.d.ts.map +1 -0
- package/dist/scene-utils/mount-override-fold.d.ts +1 -2
- package/dist/scene-utils/mount-override-fold.d.ts.map +1 -1
- package/dist/systems/sprite-animation-tick.d.ts +1 -1
- package/dist/systems/sprite-animation-tick.d.ts.map +1 -1
- package/dist/systems/transparent-sort.d.ts +1 -2
- package/dist/systems/transparent-sort.d.ts.map +1 -1
- package/dist/tilemap-register-validate.d.ts.map +1 -1
- package/package.json +34 -33
- package/src/__tests__/active-camera.unit.test.ts +19 -9
- package/src/__tests__/animation-graph-collect-roundtrip.test.ts +213 -0
- package/src/__tests__/animation-graph-serialize.unit.test.ts +171 -0
- package/src/__tests__/append-injection.test.ts +1 -1
- package/src/__tests__/asset-brand-and-name-retirement.test.ts +102 -0
- package/src/__tests__/asset-error-exhaustive.test-d.ts +62 -0
- package/src/__tests__/asset-registry-guid-reverse.test.ts +608 -0
- package/src/__tests__/asset-registry-hdr-equirect.test.ts +78 -0
- package/src/__tests__/asset-registry-mesh-pack-payload.dawn.test.ts +232 -0
- package/src/__tests__/asset-registry-mounts.test.ts +806 -0
- package/src/__tests__/asset-registry.browser.test.ts +81 -0
- package/src/__tests__/asset-registry.dawn.test.ts +94 -0
- package/src/__tests__/asset-registry.listCatalog.test.ts +170 -0
- package/src/__tests__/asset-registry.mesh-bin.test.ts +316 -0
- package/src/__tests__/asset-registry.pack-cache.test.ts +969 -0
- package/src/__tests__/asset-registry.raw-container-failfast.test.ts +225 -0
- package/src/__tests__/asset-registry.recursive.spec.ts +1397 -0
- package/src/__tests__/asset-registry.unit.test.ts +1030 -0
- package/src/__tests__/asset.unit.test.ts +7107 -0
- package/src/__tests__/audio-load-by-guid.unit.test.ts +126 -0
- package/src/__tests__/backend-selection.integration.test.ts +11 -0
- package/src/__tests__/basis-catalog-dispatch.integration.test.ts +320 -0
- package/src/__tests__/bind-group-cache-keying.test.ts +4 -4
- package/src/__tests__/block-upload-math.unit.test.ts +2 -2
- package/src/__tests__/builtin-asset-registry.unit.test.ts +112 -0
- package/src/__tests__/builtin-shader-register-e2e.test.ts +1 -1
- package/src/__tests__/cache-false-eviction.test.ts +2 -1
- package/src/__tests__/cache-isolation-matrix.test.ts +2 -1
- package/src/__tests__/camera-clear-snapshot-equivalence.unit.test.ts +5 -6
- package/src/__tests__/clamp-to-last.e2e.browser.test.ts +29 -19
- package/src/__tests__/collect-scene-asset.test.ts +49 -52
- package/src/__tests__/collect-scene-mount-collapse.test.ts +391 -0
- package/src/__tests__/collect-subtree.unit.test.ts +1 -2
- package/src/__tests__/collect-transient-children-absent.test.ts +24 -10
- package/src/__tests__/collect-transient-roundtrip.test.ts +44 -20
- package/src/__tests__/collect-transient-skip.test.ts +24 -13
- package/src/__tests__/components.test-d.ts +1 -6
- package/src/__tests__/components.unit.test.ts +20 -19
- package/src/__tests__/composite-skybox-cross-world.browser.test.ts +59 -27
- package/src/__tests__/compressed-texture-physical-extent.integration.test.ts +139 -0
- package/src/__tests__/create-renderer-assembly.integration.test.ts +42 -29
- package/src/__tests__/createRenderer-dispose.test.ts +35 -402
- package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +25 -30
- package/src/__tests__/createRenderer.unit.test.ts +1 -1
- package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +27 -63
- package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +56 -47
- package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +49 -29
- package/src/__tests__/dawn/instances-shadow.dawn.test.ts +26 -15
- package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +13 -14
- package/src/__tests__/dawn/material-alpha.dawn.test.ts +23 -31
- package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +24 -9
- package/src/__tests__/dawn/{mesh-update.dawn.test.ts → mesh-update-dawn.test.ts} +42 -134
- package/src/__tests__/dawn/mipmap-srgb-linear.dawn.test.ts +14 -7
- package/src/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.ts +16 -28
- package/src/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.ts +23 -39
- package/src/__tests__/dawn/upload-texture.dawn.test.ts +198 -0
- package/src/__tests__/dawn/user-handle-mesh-render.dawn.test.ts +12 -14
- package/src/__tests__/dawn/user-mesh-upload.dawn.test.ts +27 -22
- package/src/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.ts +25 -28
- package/src/__tests__/dawn/zero-manifest-ready.dawn.test.ts +10 -11
- package/src/__tests__/demo-sortscope-migration.unit.test.ts +5 -5
- package/src/__tests__/derive-bgl-integration.test.ts +34 -44
- package/src/__tests__/derive-render-data-skin.unit.test.ts +1 -1
- package/src/__tests__/draw-published.ts +11 -4
- package/src/__tests__/dynamic-texture-store.unit.test.ts +190 -0
- package/src/__tests__/equirect-bc6h.integration.test.ts +144 -21
- package/src/__tests__/errors.unit.test.ts +1227 -0
- package/src/__tests__/extract-frames-graceful-degradation.test.ts +3 -7
- package/src/__tests__/extract-frames-merge.test.ts +35 -22
- package/src/__tests__/extract-record-no-hardcoded-texture-fields.test.ts +5 -16
- package/src/__tests__/extract-skin-mismatch.unit.test.ts +322 -0
- package/src/__tests__/fetch-binary-decompress.test.ts +356 -0
- package/src/__tests__/four-path-compression.integration.test.ts +395 -0
- package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +1 -1
- package/src/__tests__/fullscreen-feature-host.dawn.test.ts +80 -0
- package/src/__tests__/fullscreen-post-bgl-depth.test.ts +4 -2
- package/src/__tests__/fullscreen-post-depth-params-arity.test.ts +3 -3
- package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +39 -23
- package/src/__tests__/fullscreen-post-process-pass.unit.test.ts +4 -2
- package/src/__tests__/fxaa-pixel-diff.dawn.test.ts +28 -17
- package/src/__tests__/fxaa-validation-and-resize.dawn.test.ts +29 -18
- package/src/__tests__/fxaa-zero-overhead.dawn.test.ts +16 -12
- package/src/__tests__/geometry.unit.test.ts +525 -159
- package/src/__tests__/glyph-tilemap-worldid.test.ts +1 -1
- package/src/__tests__/gpu-resource-cow-survivor.test.ts +6 -4
- package/src/__tests__/guid-for-asset.unit.test.ts +102 -0
- package/src/__tests__/handle-migration.test.ts +136 -0
- package/src/__tests__/helpers/register-runtime-components.ts +4 -2
- package/src/__tests__/helpers/register-scene-components.ts +1 -1
- package/src/__tests__/host-custom-kind-contract.test-d.ts +47 -0
- package/src/__tests__/host-custom-kind-contract.test.ts +578 -0
- package/src/__tests__/inspect-name.test.ts +139 -0
- package/src/__tests__/instances.test-d.ts +1 -1
- package/src/__tests__/instantiate-mount-deferred-wiring.test.ts +112 -0
- package/src/__tests__/light-casters-9-light.browser.test.ts +73 -76
- package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +7 -10
- package/src/__tests__/light-snapshot.test-d.ts +2 -2
- package/src/__tests__/lights-vec-negative.unit.test.ts +1 -1
- package/src/__tests__/lights.unit.test.ts +31 -511
- package/src/__tests__/loadbyguid-payload.unit.test.ts +117 -0
- package/src/__tests__/loadbyguid-texture-intern.unit.test.ts +213 -0
- package/src/__tests__/loader-extract-graceful.test.ts +146 -0
- package/src/__tests__/loader-name-survival.test.ts +213 -0
- package/src/__tests__/m3-vec-negative.unit.test.ts +3 -2
- package/src/__tests__/material-texture-uv-scale.unit.test.ts +101 -31
- package/src/__tests__/materials.unit.test.ts +10 -27
- package/src/__tests__/mesh-bin-contract.test.ts +28 -0
- package/src/__tests__/mesh-bin-skin-roundtrip.unit.test.ts +149 -0
- package/src/__tests__/mesh-bin.test.ts +38 -0
- package/src/__tests__/mesh-loader-skin-contract.unit.test.ts +120 -0
- package/src/__tests__/mesh-ssbo-grow.unit.test.ts +3 -3
- package/src/__tests__/mip-gate.unit.test.ts +1 -1
- package/src/__tests__/msaa-sprite-pixel-diff.dawn.test.ts +29 -68
- package/src/__tests__/new-kind-refs-contract.test.ts +132 -0
- package/src/__tests__/node-shims.d.ts +4 -6
- package/src/__tests__/package-promotion.test.ts +88 -0
- package/src/__tests__/package-rename.test.ts +103 -0
- package/src/__tests__/pass-selector.unit.test.ts +2 -2
- package/src/__tests__/pbr-pipeline.unit.test.ts +21 -25
- package/src/__tests__/pipeline-builder-msaa.unit.test.ts +6 -9
- package/src/__tests__/pipeline-cache-keying.unit.test.ts +6 -9
- package/src/__tests__/pipeline-spec.test.ts +16 -177
- package/src/__tests__/pipeline.unit.test.ts +154 -1693
- package/src/__tests__/point-light-shadow.dawn.test.ts +33 -42
- package/src/__tests__/point-light-shadow.unit.test.ts +19 -60
- package/src/__tests__/post-process-error-codes.unit.test.ts +4 -1
- package/src/__tests__/post-process-params-component.unit.test.ts +1 -1
- package/src/__tests__/post-process-params-extract.unit.test.ts +2 -5
- package/src/__tests__/postprocess-camera-consistency.test.ts +4 -7
- package/src/__tests__/profiler-assembly.integration.test.ts +1 -1
- package/src/__tests__/propagate-transforms.dawn.test.ts +12 -11
- package/src/__tests__/record-worldid-isolation.test.ts +7 -29
- package/src/__tests__/recover-error-exhaustive.test-d.ts +1 -1
- package/src/__tests__/render-error-exhaustive.test-d.ts +117 -71
- package/src/__tests__/render-feature-assembly.test-d.ts +20 -9
- package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +8 -6
- package/src/__tests__/render-feature-prepared-graphics.browser.test.ts +65 -559
- package/src/__tests__/render-feature-prepared-graphics.dawn.test.ts +57 -544
- package/src/__tests__/render-feature-prepared-graphics.fixture.ts +104 -0
- package/src/__tests__/render-feature-prepared-graphics.integration.test.ts +40 -248
- package/src/__tests__/render-feature-prepared-graphics.regression.integration.test.ts +83 -340
- package/src/__tests__/render-feature-recover.integration.test.ts +9 -49
- package/src/__tests__/render-feature-runtime-surface.test-d.ts +17 -20
- package/src/__tests__/render-schema-consumer.integration.test.ts +20 -13
- package/src/__tests__/render-schema-owner-boundary.unit.test.ts +2 -6
- package/src/__tests__/render-system-cross-world-overlay-queue.test.ts +5 -5
- package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +16 -31
- package/src/__tests__/render-system-extract.test.ts +36 -51
- package/src/__tests__/render-system-extract.unit.test.ts +360 -0
- package/src/__tests__/render-system-fold-bucket.unit.test.ts +3 -5
- package/src/__tests__/render-system-fold-fallback.unit.test.ts +6 -3
- package/src/__tests__/render-system-fold-material.unit.test.ts +3 -5
- package/src/__tests__/render-system-fold-metrics.unit.test.ts +5 -5
- package/src/__tests__/render-system-fold-modegate.unit.test.ts +6 -6
- package/src/__tests__/render-system-fold.dawn.test.ts +7 -5
- package/src/__tests__/render-system-mega.test.ts +292 -190
- package/src/__tests__/render-system-owner-split-contract.test.ts +10 -32
- package/src/__tests__/render-system-record-multi-material-textureview.test.ts +59 -45
- package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +23 -29
- package/src/__tests__/render-system-record.test.ts +398 -235
- package/src/__tests__/render-system-record.unit.test.ts +25 -26
- package/src/__tests__/render-system-skin-bg.unit.test.ts +8 -12
- package/src/__tests__/renderer-consumer.test-d.ts +16 -3
- package/src/__tests__/renderer-health.unit.test.ts +26 -916
- package/src/__tests__/renderer-lifecycle.integration.test.ts +19 -6
- package/src/__tests__/renderer-recover.unit.test.ts +49 -1069
- package/src/__tests__/renderer-result.test-d.ts +19 -9
- package/src/__tests__/renderer-surface.unit.test.ts +3 -5
- package/src/__tests__/renderer-test-utils.ts +56 -0
- package/src/__tests__/renderer.test-d.ts +61 -0
- package/src/__tests__/resolve-asset-handle-err.test.ts +111 -0
- package/src/__tests__/resolve-asset-handle.unit.test.ts +64 -0
- package/src/__tests__/resolve-depth-only-view.test.ts +1 -1
- package/src/__tests__/resolveName-fallback.test.ts +64 -0
- package/src/__tests__/resolveName-null-package.test.ts +38 -0
- package/src/__tests__/resolveName-unified-entry.test.ts +65 -0
- package/src/__tests__/resolveName.test.ts +64 -0
- package/src/__tests__/rhi-null-command-flow.unit.test.ts +56 -260
- package/src/__tests__/rhi-null-renderer-lifecycle.unit.test.ts +41 -169
- package/src/__tests__/roots-to-scene-asset.test.ts +199 -93
- package/src/__tests__/roundtrip-primitive.test.ts +351 -0
- package/src/__tests__/scene-bare-guid-refs-instantiate.test.ts +123 -0
- package/src/__tests__/scene-equirect-roundtrip.test.ts +103 -16
- package/src/__tests__/scene-instance-authoring.integration.test.ts +8 -0
- package/src/__tests__/scene-instance-bridge.integration.test.ts +1 -1
- package/src/__tests__/scene-instance-component.test.ts +1 -1
- package/src/__tests__/scene-mount-fixed-point.test.ts +257 -0
- package/src/__tests__/scene-mount-roundtrip.test.ts +987 -0
- package/src/__tests__/scene-mount-wrapper-roundtrip.test.ts +202 -0
- package/src/__tests__/scene-sugar-instantiate.test.ts +324 -0
- package/src/__tests__/serialize-mounts-roundtrip.test.ts +533 -0
- package/src/__tests__/serialize-scene-asset.test.ts +219 -22
- package/src/__tests__/shadow-caster-empty-schema.test.ts +3 -3
- package/src/__tests__/shadow-csm-cascade-loadop.test.ts +37 -17
- package/src/__tests__/shadow-csm-component.test.ts +3 -5
- package/src/__tests__/shadow-csm-extract.test.ts +2 -100
- package/src/__tests__/shadow-csm-orthoz.test.ts +2 -16
- package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +19 -14
- package/src/__tests__/shadow-csm-tile-consistency.test.ts +32 -26
- package/src/__tests__/shadow-csm-ubo.dawn.test.ts +8 -49
- package/src/__tests__/shadow-csm-ubo.test.ts +3 -25
- package/src/__tests__/shadow-csm-viewport.browser.test.ts +1 -1
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +67 -56
- package/src/__tests__/shadow-m1.dawn.test.ts +8 -9
- package/src/__tests__/shadow-mesh-ssbo-order.test.ts +11 -27
- package/src/__tests__/skin-errors.unit.test.ts +1 -1
- package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +7 -5
- package/src/__tests__/skylight-lazy-projection.test.ts +36 -15
- package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +5 -5
- package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +47 -64
- package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +15 -14
- package/src/__tests__/sprite-lit-extract-branch.test.ts +1 -1
- package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +1 -1
- package/src/__tests__/ssao-bgl.test.ts +16 -9
- package/src/__tests__/ssao-buffers.test.ts +2 -2
- package/src/__tests__/ssao-data.test.ts +2 -2
- package/src/__tests__/ssao-errors.test.ts +1 -1
- package/src/__tests__/ssao-passes.test.ts +68 -392
- package/src/__tests__/ssao-pipelines.test.ts +1 -1
- package/src/__tests__/ssao-uniform-layout.test.ts +8 -6
- package/src/__tests__/stencil-outline-pixel.dawn.test.ts +25 -17
- package/src/__tests__/swap-chain-format.unit.test.ts +5 -7
- package/src/__tests__/systems.unit.test.ts +536 -1326
- package/src/__tests__/template-game-default-api-contract.test.ts +362 -0
- package/src/__tests__/text.unit.test.ts +56 -33
- package/src/__tests__/tilemap-childed-despawn.test.ts +8 -14
- package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +8 -12
- package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +2 -1
- package/src/__tests__/tilemap-chunk-extract.test.ts +13 -17
- package/src/__tests__/tilemap-dirty-rebuild.test.ts +7 -11
- package/src/__tests__/tilemap-material-cache.test.ts +8 -13
- package/src/__tests__/tilemap-multi-atlas.test.ts +12 -32
- package/src/__tests__/tilemap-owner-boundary.unit.test.ts +5 -2
- package/src/__tests__/tilemap-region-pack.test.ts +8 -12
- package/src/__tests__/tilemap-spawn-flip-pivot.test.ts +8 -12
- package/src/__tests__/tilemap-uv-inset.test.ts +11 -14
- package/src/__tests__/tilemap-validate.test.ts +1 -1
- package/src/__tests__/tileset-asset-validate.test.ts +638 -0
- package/src/__tests__/transcode-fallback.unit.test.ts +207 -0
- package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +36 -28
- package/src/__tests__/transient-fields-collect.test.ts +28 -21
- package/src/__tests__/transient-runtime-behavior.test.ts +227 -0
- package/src/__tests__/transparent-sort-tilemap-sprite-interleave.test.ts +4 -4
- package/src/__tests__/variant-selection.unit.test.ts +1 -1
- package/src/__tests__/video-extract-bindgroup.dawn.test.ts +89 -136
- package/src/__tests__/video-loader-consumption.test.ts +86 -0
- package/src/__tests__/video-loader-smoke.dawn.test.ts +60 -0
- package/src/__tests__/view-ubo-layout.browser.test.ts +0 -22
- package/src/__tests__/world-entity-key.test.ts +1 -1
- package/src/__tests__/world-scene-despawn.test.ts +1 -1
- package/src/__tests__/world-scene-instantiate.test.ts +2 -36
- package/src/__tests__/world-scene-nested.test.ts +1 -1
- package/src/__tests__/world-scene-override.test.ts +1 -1
- package/src/backend-selection.ts +69 -0
- package/src/collect-scene-asset.ts +35 -23
- package/src/components/__tests__/camera.test-d.ts +1 -1
- package/src/components/__tests__/camera.test.ts +1 -1
- package/src/components/__tests__/sprite-animation.test-d.ts +2 -2
- package/src/components/__tests__/tile-layer.test-d.ts +1 -1
- package/src/components/__tests__/tile-layer.unit.test.ts +2 -2
- package/src/createRenderer.ts +24 -36
- package/src/errors/environment.ts +1 -1
- package/src/index.ts +51 -113
- package/src/renderer-host.ts +33 -0
- package/src/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.ts +1 -1
- package/src/scene-instances/index.ts +4 -0
- package/src/scene-utils/mount-override-fold.ts +3 -7
- package/src/systems/__tests__/transparent-sort.bench.ts +3 -3
- package/src/systems/sprite-animation-tick.ts +1 -1
- package/src/systems/transparent-sort.ts +38 -38
- package/src/tilemap-register-validate.ts +4 -4
- package/dist/__tests__/bind-group-cache-binding.test.d.ts +0 -2
- package/dist/__tests__/bind-group-cache-binding.test.d.ts.map +0 -1
- package/dist/__tests__/bind-group-cache-frame.test.d.ts +0 -2
- package/dist/__tests__/bind-group-cache-frame.test.d.ts.map +0 -1
- package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts +0 -2
- package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts +0 -2
- package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-manifest.d.ts +0 -131
- package/dist/__tests__/fog-producer-manifest.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-pixel-probe.d.ts +0 -42
- package/dist/__tests__/fog-producer-pixel-probe.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-pixel.browser.test.d.ts +0 -2
- package/dist/__tests__/fog-producer-pixel.browser.test.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts +0 -2
- package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-real-fixture.d.ts +0 -5
- package/dist/__tests__/fog-producer-real-fixture.d.ts.map +0 -1
- package/dist/__tests__/fog-producer-vfx-effect.d.ts +0 -3
- package/dist/__tests__/fog-producer-vfx-effect.d.ts.map +0 -1
- package/dist/__tests__/fog-scene-asset.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-scene-asset.integration.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts +0 -2
- package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-resource.test.d.ts +0 -2
- package/dist/__tests__/gpu-resource.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts +0 -2
- package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-buffers.unit.test.d.ts +0 -2
- package/dist/__tests__/hdrp-buffers.unit.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts +0 -2
- package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts +0 -2
- package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts +0 -2
- package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts.map +0 -1
- package/dist/__tests__/hdrp-ssao-boundary.test.d.ts +0 -2
- package/dist/__tests__/hdrp-ssao-boundary.test.d.ts.map +0 -1
- package/dist/__tests__/hdrp-ssao-falsification.test.d.ts +0 -2
- package/dist/__tests__/hdrp-ssao-falsification.test.d.ts.map +0 -1
- package/dist/__tests__/helpers/primitive-world.d.ts +0 -8
- package/dist/__tests__/helpers/primitive-world.d.ts.map +0 -1
- package/dist/__tests__/helpers/render-asset-port.d.ts +0 -15
- package/dist/__tests__/helpers/render-asset-port.d.ts.map +0 -1
- package/dist/__tests__/helpers/scene-asset-port.d.ts +0 -9
- package/dist/__tests__/helpers/scene-asset-port.d.ts.map +0 -1
- package/dist/__tests__/material-derived-coordinates.integration.test.d.ts +0 -2
- package/dist/__tests__/material-derived-coordinates.integration.test.d.ts.map +0 -1
- package/dist/__tests__/pipeline-layout-selection.test.d.ts +0 -2
- package/dist/__tests__/pipeline-layout-selection.test.d.ts.map +0 -1
- package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts +0 -2
- package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts.map +0 -1
- package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts +0 -2
- package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts +0 -2
- package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts.map +0 -1
- package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts +0 -2
- package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-caster-membership.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-caster-membership.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-pssm.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-pssm.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-csm-viewport.test.d.ts +0 -2
- package/dist/__tests__/shadow-csm-viewport.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-m2.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-m2.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-m3-calibrate.d.ts +0 -83
- package/dist/__tests__/shadow-m3-calibrate.d.ts.map +0 -1
- package/dist/__tests__/shadow-m3.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-m3.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts +0 -2
- package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/temporal-off-path.unit.test.d.ts +0 -2
- package/dist/__tests__/temporal-off-path.unit.test.d.ts.map +0 -1
- package/dist/__tests__/video-cache-regression.unit.test.d.ts +0 -2
- package/dist/__tests__/video-cache-regression.unit.test.d.ts.map +0 -1
- package/dist/asset-kind.d.ts +0 -4
- package/dist/asset-kind.d.ts.map +0 -1
- package/dist/errors/sprite-animation.d.ts +0 -3
- package/dist/errors/sprite-animation.d.ts.map +0 -1
- package/dist/scene-asset-port.d.ts +0 -17
- package/dist/scene-asset-port.d.ts.map +0 -1
- package/dist/scene-collect-errors.d.ts +0 -22
- package/dist/scene-collect-errors.d.ts.map +0 -1
- package/dist/shadow-m3-calibrate.d.ts +0 -40
- package/dist/shadow-m3-calibrate.d.ts.map +0 -1
- package/src/__tests__/bind-group-cache-binding.test.ts +0 -2513
- package/src/__tests__/bind-group-cache-frame.test.ts +0 -1511
- package/src/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.ts +0 -204
- package/src/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.ts +0 -297
- package/src/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.ts +0 -271
- package/src/__tests__/dispatch-fullscreen-pass-params.unit.test.ts +0 -321
- package/src/__tests__/fog-producer-manifest.ts +0 -162
- package/src/__tests__/fog-producer-pixel-probe.ts +0 -263
- package/src/__tests__/fog-producer-pixel.browser.test.ts +0 -26
- package/src/__tests__/fog-producer-pixel.dawn.test.ts +0 -55
- package/src/__tests__/fog-producer-real-fixture.ts +0 -805
- package/src/__tests__/fog-producer-vfx-effect.ts +0 -272
- package/src/__tests__/fog-scene-asset.integration.test.ts +0 -123
- package/src/__tests__/gpu-resource-store-cubemap-status.test.ts +0 -207
- package/src/__tests__/gpu-resource.test.ts +0 -1206
- package/src/__tests__/hdrp-bgl-slots.browser.test.ts +0 -50
- package/src/__tests__/hdrp-buffers.unit.test.ts +0 -70
- package/src/__tests__/hdrp-execute-filter.unit.test.ts +0 -200
- package/src/__tests__/hdrp-gbuffer-attachments.browser.test.ts +0 -64
- package/src/__tests__/hdrp-pipeline-asset-type.test-d.ts +0 -139
- package/src/__tests__/hdrp-ssao-boundary.test.ts +0 -237
- package/src/__tests__/hdrp-ssao-falsification.test.ts +0 -289
- package/src/__tests__/helpers/primitive-world.ts +0 -91
- package/src/__tests__/helpers/render-asset-port.ts +0 -65
- package/src/__tests__/helpers/scene-asset-port.ts +0 -23
- package/src/__tests__/material-derived-coordinates.integration.test.ts +0 -100
- package/src/__tests__/pipeline-layout-selection.test.ts +0 -298
- package/src/__tests__/post-process-reads-narrowing.test-d.ts +0 -52
- package/src/__tests__/post-process-register-roundtrip.dawn.test.ts +0 -230
- package/src/__tests__/render-feature-zero-feature.browser.test.ts +0 -152
- package/src/__tests__/render-pipeline-trivial.dawn.test.ts +0 -525
- package/src/__tests__/shadow-csm-caster-membership.test.ts +0 -232
- package/src/__tests__/shadow-csm-pssm.test.ts +0 -142
- package/src/__tests__/shadow-csm-temporal.browser.test.ts +0 -145
- package/src/__tests__/shadow-csm-viewport.test.ts +0 -74
- package/src/__tests__/shadow-m2.dawn.test.ts +0 -394
- package/src/__tests__/shadow-m3-calibrate-run.dawn.test.ts +0 -248
- package/src/__tests__/shadow-m3-calibrate.ts +0 -203
- package/src/__tests__/shadow-m3.dawn.test.ts +0 -288
- package/src/__tests__/shadow-probe-control-flow.dawn.test.ts +0 -264
- package/src/__tests__/shadow-quality-metrics.dawn.test.ts +0 -324
- package/src/__tests__/temporal-off-path.unit.test.ts +0 -69
- package/src/__tests__/video-cache-regression.unit.test.ts +0 -186
- package/src/asset-kind.ts +0 -7
- package/src/errors/sprite-animation.ts +0 -5
- package/src/scene-asset-port.ts +0 -32
- package/src/scene-collect-errors.ts +0 -30
- package/src/shadow-m3-calibrate.ts +0 -171
|
@@ -1,525 +0,0 @@
|
|
|
1
|
-
// render-pipeline-trivial.dawn.test.ts
|
|
2
|
-
// feat-20260601-customizable-render-pipeline-seam-and-dogfood-rend M2 / w11.
|
|
3
|
-
//
|
|
4
|
-
// Structured dawn-node smoke for the customizable render-pipeline seam. This single test
|
|
5
|
-
// file is BOTH the AC-02 (register + install + run a trivial custom pipeline 300 frames,
|
|
6
|
-
// 0 RhiError) AND the AC-03 (install two RenderPipelineAssets sharing ONE logic id but
|
|
7
|
-
// differing only in config.passCount, observe perFramePassNames differ + a graph rebuild --
|
|
8
|
-
// the genuine one-logic-N-configs proof that config is threaded into buildGraph and is
|
|
9
|
-
// NON-no-op; feat-20260601 verify round 2 fixed the seam that formerly dropped config) AND
|
|
10
|
-
// the AC-08 proof: the trivial pipeline's buildGraph / execute closures take a `RenderPipelineContext`
|
|
11
|
-
// argument and reference ONLY its documented fields. A `ctx.internals` access does NOT
|
|
12
|
-
// type-check (the kitchen-sink is gone) - that compile error is the load-bearing AC-08
|
|
13
|
-
// oracle, asserted statically below via an `@ts-expect-error` line.
|
|
14
|
-
//
|
|
15
|
-
// Follows the fxaa-zero-overhead.dawn.test.ts pattern for canvas mock + device capture.
|
|
16
|
-
|
|
17
|
-
import { World } from '@forgeax/engine-ecs';
|
|
18
|
-
import { createPrimitiveMesh } from '@forgeax/engine-geometry';
|
|
19
|
-
import type { RenderPipeline, RenderPipelineContext } from '@forgeax/engine-render/internal';
|
|
20
|
-
import { Camera, MeshFilter, MeshRenderer } from '@forgeax/engine-render/internal';
|
|
21
|
-
import { Transform } from '@forgeax/engine-scene';
|
|
22
|
-
import type { RenderPipelineAsset } from '@forgeax/engine-types';
|
|
23
|
-
import { describe, expect, it } from 'vitest';
|
|
24
|
-
import { createRenderer } from '../index';
|
|
25
|
-
import { drawPublished } from './draw-published';
|
|
26
|
-
|
|
27
|
-
const WIDTH = 256;
|
|
28
|
-
const HEIGHT = 256;
|
|
29
|
-
|
|
30
|
-
const TEXTURE_USAGE_COPY_SRC = 0x01;
|
|
31
|
-
const TEXTURE_USAGE_RENDER_ATTACHMENT = 0x10;
|
|
32
|
-
|
|
33
|
-
const ENGINE_MANIFEST = await (async () => {
|
|
34
|
-
const { buildEngineShaderManifest } = await import('@forgeax/engine-vite-plugin-shader');
|
|
35
|
-
return buildEngineShaderManifest();
|
|
36
|
-
})();
|
|
37
|
-
const ENGINE_MANIFEST_URL = `data:application/json,${encodeURIComponent(
|
|
38
|
-
JSON.stringify(ENGINE_MANIFEST),
|
|
39
|
-
)}`;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Build the trivial custom RenderPipeline. ONE logic id; its topology is sized at
|
|
43
|
-
* `buildGraph` time by `data.config?.passCount` (the install-time `RenderPipelineAsset.config`
|
|
44
|
-
* threaded through the pipeline seam, feat-20260601 verify round 2). Two `RenderPipelineAsset`s
|
|
45
|
-
* sharing this one logic id but differing only in `config.passCount` install to observably
|
|
46
|
-
* different `perFramePassNames` (AC-03, one-logic-N-configs).
|
|
47
|
-
*
|
|
48
|
-
* `data.config?.passCount ?? 1` is the read: missing config defaults to a single pass so a
|
|
49
|
-
* config-less install still produces a non-empty frame (AC-02).
|
|
50
|
-
*
|
|
51
|
-
* AC-08 evidence: every closure below takes a `RenderPipelineContext` and reaches ONLY its
|
|
52
|
-
* documented fields (`ctx.encoder`, `ctx.view`, `ctx.runtime.device`, `ctx.frameState`). It
|
|
53
|
-
* CANNOT reach `ctx.internals` - that is a compile error (the `@ts-expect-error` test at the
|
|
54
|
-
* bottom of this file pins that). Pass 0 clears the swap-chain view to a distinctive green
|
|
55
|
-
* so the produced frame is observably non-empty (AC-02); passes 1..N-1 are no-ops. The
|
|
56
|
-
* config-driven pass count drives `perFramePassNames` (AC-03).
|
|
57
|
-
*/
|
|
58
|
-
function makeTrivialPipeline(): RenderPipeline {
|
|
59
|
-
return {
|
|
60
|
-
build({ graph, contributeFeatures }, topology) {
|
|
61
|
-
const passCount = topology.config?.passCount ?? 1;
|
|
62
|
-
const surface = graph.importTexture(
|
|
63
|
-
'custom-surface',
|
|
64
|
-
{
|
|
65
|
-
format: topology.surface.storageFormat,
|
|
66
|
-
size: 'surface',
|
|
67
|
-
usage: TEXTURE_USAGE_COPY_SRC | TEXTURE_USAGE_RENDER_ATTACHMENT,
|
|
68
|
-
viewFormats:
|
|
69
|
-
topology.surface.storageFormat === topology.surface.viewFormat
|
|
70
|
-
? []
|
|
71
|
-
: [topology.surface.viewFormat],
|
|
72
|
-
},
|
|
73
|
-
(frame) => frame.currentTexture,
|
|
74
|
-
);
|
|
75
|
-
if (!surface.ok) return surface;
|
|
76
|
-
const surfaceView = graph.importView(
|
|
77
|
-
surface.value,
|
|
78
|
-
{ label: 'custom-surface.view', format: topology.surface.viewFormat },
|
|
79
|
-
(frame) => frame.view,
|
|
80
|
-
);
|
|
81
|
-
if (!surfaceView.ok) return surfaceView;
|
|
82
|
-
for (let i = 0; i < passCount; i++) {
|
|
83
|
-
const added = graph.addRasterPass(`custom-pass-${i}`, {
|
|
84
|
-
accesses: [{ resource: surfaceView.value, usage: 'color-attachment' }],
|
|
85
|
-
colorAttachments: [
|
|
86
|
-
{
|
|
87
|
-
view: surfaceView.value,
|
|
88
|
-
clearValue: { r: 0, g: 0.6, b: 0, a: 1 },
|
|
89
|
-
loadOp: i === 0 ? 'clear' : 'load',
|
|
90
|
-
storeOp: 'store',
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
encode: () => undefined,
|
|
94
|
-
});
|
|
95
|
-
if (!added.ok) return added;
|
|
96
|
-
}
|
|
97
|
-
return contributeFeatures([]);
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
interface DawnHarness {
|
|
103
|
-
renderer: Awaited<ReturnType<typeof createRenderer>>;
|
|
104
|
-
device: GPUDevice;
|
|
105
|
-
renderTarget: GPUTexture;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
async function bootDawn(): Promise<DawnHarness | null> {
|
|
109
|
-
const dawnAvailable = typeof globalThis.navigator?.gpu?.requestAdapter === 'function';
|
|
110
|
-
if (!dawnAvailable) {
|
|
111
|
-
throw new Error('dawn-node navigator.gpu not injected; vitest.setup-webgpu.ts regressed');
|
|
112
|
-
}
|
|
113
|
-
let sharedDevice: GPUDevice | undefined;
|
|
114
|
-
const originalRequestAdapter = globalThis.navigator.gpu.requestAdapter.bind(
|
|
115
|
-
globalThis.navigator.gpu,
|
|
116
|
-
);
|
|
117
|
-
globalThis.navigator.gpu.requestAdapter = async (opts) => {
|
|
118
|
-
const rawAdapter = await originalRequestAdapter(opts);
|
|
119
|
-
if (rawAdapter === null) return rawAdapter;
|
|
120
|
-
const originalRequestDevice = rawAdapter.requestDevice.bind(rawAdapter);
|
|
121
|
-
rawAdapter.requestDevice = async (desc) => {
|
|
122
|
-
const dev = await originalRequestDevice(desc);
|
|
123
|
-
if (sharedDevice === undefined) sharedDevice = dev;
|
|
124
|
-
return dev;
|
|
125
|
-
};
|
|
126
|
-
return rawAdapter;
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
let renderTarget: GPUTexture | undefined;
|
|
130
|
-
const ensureRenderTarget = (device: GPUDevice, format: GPUTextureFormat): GPUTexture => {
|
|
131
|
-
if (renderTarget !== undefined) return renderTarget;
|
|
132
|
-
renderTarget = device.createTexture({
|
|
133
|
-
size: { width: WIDTH, height: HEIGHT, depthOrArrayLayers: 1 },
|
|
134
|
-
format,
|
|
135
|
-
usage: TEXTURE_USAGE_RENDER_ATTACHMENT | TEXTURE_USAGE_COPY_SRC,
|
|
136
|
-
viewFormats: ['rgba8unorm-srgb'],
|
|
137
|
-
});
|
|
138
|
-
return renderTarget;
|
|
139
|
-
};
|
|
140
|
-
const mockCanvas = {
|
|
141
|
-
width: WIDTH,
|
|
142
|
-
height: HEIGHT,
|
|
143
|
-
getContext(kind: string): unknown {
|
|
144
|
-
if (kind !== 'webgpu') return null;
|
|
145
|
-
return {
|
|
146
|
-
configure(desc: { device: GPUDevice; format?: GPUTextureFormat }) {
|
|
147
|
-
ensureRenderTarget(desc.device, desc.format ?? 'rgba8unorm');
|
|
148
|
-
},
|
|
149
|
-
unconfigure() {},
|
|
150
|
-
getCurrentTexture(): GPUTexture {
|
|
151
|
-
if (renderTarget === undefined) {
|
|
152
|
-
if (sharedDevice === undefined)
|
|
153
|
-
throw new Error('render target requested before device captured');
|
|
154
|
-
return ensureRenderTarget(sharedDevice, 'rgba8unorm');
|
|
155
|
-
}
|
|
156
|
-
return renderTarget;
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
},
|
|
160
|
-
addEventListener() {},
|
|
161
|
-
removeEventListener() {},
|
|
162
|
-
} as unknown as HTMLCanvasElement;
|
|
163
|
-
|
|
164
|
-
let renderer: Awaited<ReturnType<typeof createRenderer>>;
|
|
165
|
-
try {
|
|
166
|
-
renderer = await createRenderer(mockCanvas, {}, { shaderManifestUrl: ENGINE_MANIFEST_URL });
|
|
167
|
-
} finally {
|
|
168
|
-
globalThis.navigator.gpu.requestAdapter = originalRequestAdapter;
|
|
169
|
-
}
|
|
170
|
-
expect(renderer.backend).toBe('webgpu');
|
|
171
|
-
const ready = await renderer.ready;
|
|
172
|
-
expect(ready.ok).toBe(true);
|
|
173
|
-
if (!ready.ok) return null;
|
|
174
|
-
if (sharedDevice === undefined) {
|
|
175
|
-
throw new Error('dawn device never captured through requestDevice shim');
|
|
176
|
-
}
|
|
177
|
-
// Create the swap-chain render target eagerly. The mock canvas creates it lazily inside
|
|
178
|
-
// getCurrentTexture(), which the first renderer.draw() triggers - but bootDawn returns
|
|
179
|
-
// before any draw, so without this eager creation renderTarget stays undefined and the
|
|
180
|
-
// harness would (formerly) return null, making the AC-02/AC-03 tests no-op (vacuous green).
|
|
181
|
-
const target = ensureRenderTarget(sharedDevice, 'rgba8unorm');
|
|
182
|
-
return { renderer, device: sharedDevice, renderTarget: target };
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function spawnCubeScene(world: World): void {
|
|
186
|
-
const cubeHandle = world.internSharedRef('MeshAsset', createPrimitiveMesh('cube').unwrap());
|
|
187
|
-
world.spawn(
|
|
188
|
-
{
|
|
189
|
-
component: Transform,
|
|
190
|
-
data: {
|
|
191
|
-
pos: [0, 0, 0],
|
|
192
|
-
quat: [0, 0, 0, 1],
|
|
193
|
-
scale: [1, 1, 1],
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
{ component: MeshFilter, data: { assetHandle: cubeHandle } },
|
|
197
|
-
{ component: MeshRenderer, data: {} },
|
|
198
|
-
);
|
|
199
|
-
world.spawn(
|
|
200
|
-
{
|
|
201
|
-
component: Transform,
|
|
202
|
-
data: {
|
|
203
|
-
pos: [0, 0, 3],
|
|
204
|
-
quat: [0, 0, 0, 1],
|
|
205
|
-
scale: [1, 1, 1],
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
{ component: Camera, data: { fov: Math.PI / 4, aspect: 1, near: 0.1, far: 100 } },
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
describe('feat-20260601 M2 w11: customizable render pipeline (dawn)', () => {
|
|
213
|
-
it('AC-02: register + install a trivial custom pipeline, draw 300 frames, 0 RhiError', async () => {
|
|
214
|
-
const harness = await bootDawn();
|
|
215
|
-
if (harness === null) return;
|
|
216
|
-
const { renderer, device } = harness;
|
|
217
|
-
|
|
218
|
-
let rhiErrors = 0;
|
|
219
|
-
renderer.onError(() => {
|
|
220
|
-
rhiErrors++;
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
renderer.registerPipeline('test::trivial', makeTrivialPipeline());
|
|
224
|
-
const installed = renderer.installPipeline({
|
|
225
|
-
kind: 'render-pipeline',
|
|
226
|
-
pipelineId: 'test::trivial',
|
|
227
|
-
config: { passCount: 1 },
|
|
228
|
-
});
|
|
229
|
-
expect(installed.ok).toBe(true);
|
|
230
|
-
|
|
231
|
-
const world = new World();
|
|
232
|
-
spawnCubeScene(world);
|
|
233
|
-
|
|
234
|
-
for (let f = 0; f < 300; f++) {
|
|
235
|
-
const drawn = drawPublished(renderer, world);
|
|
236
|
-
expect(drawn.ok).toBe(true);
|
|
237
|
-
}
|
|
238
|
-
await device.queue.onSubmittedWorkDone();
|
|
239
|
-
|
|
240
|
-
// AC-02: zero structured RhiError across 300 frames.
|
|
241
|
-
expect(rhiErrors).toBe(0);
|
|
242
|
-
// AC-02 non-empty frame proof: the custom pipeline drove the per-frame graph and the
|
|
243
|
-
// declared pass set is present (falsification anchor: a buildGraph -> null returns an
|
|
244
|
-
// empty perFramePassNames array, which would fail this assertion).
|
|
245
|
-
expect(renderer.perFramePassNames).toEqual(['custom-pass-0']);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
it('AC-03: ONE logic id + two configs (passCount 1 vs 2) rebuilds the graph + changes perFramePassNames', async () => {
|
|
249
|
-
const harness = await bootDawn();
|
|
250
|
-
if (harness === null) return;
|
|
251
|
-
const { renderer, device } = harness;
|
|
252
|
-
|
|
253
|
-
let rhiErrors = 0;
|
|
254
|
-
renderer.onError(() => {
|
|
255
|
-
rhiErrors++;
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
// ONE logic id. The config-driven difference is genuine (not faked by two closures): the
|
|
259
|
-
// trivial pipeline's buildGraph reads `data.config?.passCount` (the install-time config
|
|
260
|
-
// threaded through the seam). Two assets share this single logic id and differ ONLY in
|
|
261
|
-
// config.passCount.
|
|
262
|
-
renderer.registerPipeline('test::trivial', makeTrivialPipeline());
|
|
263
|
-
|
|
264
|
-
const assetA: RenderPipelineAsset = {
|
|
265
|
-
kind: 'render-pipeline',
|
|
266
|
-
pipelineId: 'test::trivial',
|
|
267
|
-
config: { passCount: 1 },
|
|
268
|
-
};
|
|
269
|
-
const assetB: RenderPipelineAsset = {
|
|
270
|
-
kind: 'render-pipeline',
|
|
271
|
-
pipelineId: 'test::trivial',
|
|
272
|
-
config: { passCount: 2 },
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
const world = new World();
|
|
276
|
-
spawnCubeScene(world);
|
|
277
|
-
|
|
278
|
-
// Install A (config.passCount=1) + draw -> one custom pass.
|
|
279
|
-
expect(renderer.installPipeline(assetA).ok).toBe(true);
|
|
280
|
-
expect(drawPublished(renderer, world).ok).toBe(true);
|
|
281
|
-
const passesAfterA = [...renderer.perFramePassNames];
|
|
282
|
-
|
|
283
|
-
// Install B (same logic id, config.passCount=2) + draw -> the install bumps the
|
|
284
|
-
// install-epoch brand-number, forcing a rebuild; buildGraph then reads the new
|
|
285
|
-
// config and declares two passes. This is the falsifiable proof that config is NON-no-op:
|
|
286
|
-
// if installPipeline dropped config (the verify-round-1 defect) passesAfterB would equal
|
|
287
|
-
// passesAfterA and the assertion below would fail.
|
|
288
|
-
expect(renderer.installPipeline(assetB).ok).toBe(true);
|
|
289
|
-
expect(drawPublished(renderer, world).ok).toBe(true);
|
|
290
|
-
const passesAfterB = [...renderer.perFramePassNames];
|
|
291
|
-
|
|
292
|
-
await device.queue.onSubmittedWorkDone();
|
|
293
|
-
|
|
294
|
-
// AC-03 (a)+(b): same logic id, the graph rebuilt (different pass set) and the
|
|
295
|
-
// config-driven pass count is observable through perFramePassNames.
|
|
296
|
-
expect(passesAfterA).toEqual(['custom-pass-0']);
|
|
297
|
-
expect(passesAfterB).toEqual(['custom-pass-0', 'custom-pass-1']);
|
|
298
|
-
expect(passesAfterA).not.toEqual(passesAfterB);
|
|
299
|
-
// AC-03 (c): 0 RhiError across both installs + draws.
|
|
300
|
-
expect(rhiErrors).toBe(0);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
it('AC-08: a custom pipeline closure cannot reach ctx.internals (compile-time oracle)', () => {
|
|
304
|
-
// The load-bearing AC-08 proof is static: the kitchen-sink `internals` field is GONE
|
|
305
|
-
// from RenderPipelineContext. The line below MUST fail to type-check; if a future
|
|
306
|
-
// change re-adds `internals` to the public ctx, the `@ts-expect-error` becomes unused
|
|
307
|
-
// and tsc fails the build - turning this into a falsifiable guard.
|
|
308
|
-
const probe = (ctx: RenderPipelineContext): unknown =>
|
|
309
|
-
// @ts-expect-error - ctx.internals is intentionally unreachable (AC-08 oracle)
|
|
310
|
-
ctx.internals;
|
|
311
|
-
// The clean named surfaces ARE reachable (no error expected).
|
|
312
|
-
const probeClean = (ctx: RenderPipelineContext): unknown => [
|
|
313
|
-
ctx.assets,
|
|
314
|
-
ctx.store,
|
|
315
|
-
ctx.pipelineState,
|
|
316
|
-
ctx.runtime,
|
|
317
|
-
];
|
|
318
|
-
expect(typeof probe).toBe('function');
|
|
319
|
-
expect(typeof probeClean).toBe('function');
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
// feat-20260604-resource-owning-render-graph-and-fullscreen-postpr M3 / w17:
|
|
323
|
-
// AC-11 (addScenePass primitive) + AC-17 (end-to-end scene -> graph-owned RT
|
|
324
|
-
// -> fullscreen post-process readback). The trivial pipeline above only clears
|
|
325
|
-
// the swap-chain; below proves `g.addColorTarget` + `g.addScenePass` +
|
|
326
|
-
// `g.addFullscreenPass` form the public vocabulary an AI user pipeline uses.
|
|
327
|
-
//
|
|
328
|
-
// The urp pipeline is exercised through createRenderer's default
|
|
329
|
-
// install — one frame with a non-empty scene must read back non-clear pixels
|
|
330
|
-
// through every pass (geometry, tonemap, fxaa). Without addScenePass /
|
|
331
|
-
// addFullscreenPass actually drawing the scene into the graph-owned RT and
|
|
332
|
-
// composing into the swap-chain, the readback would equal the clear colour —
|
|
333
|
-
// which the falsify test below asserts when no scene is spawned.
|
|
334
|
-
it('AC-11/17: urp addScenePass + addFullscreenPass renders scene non-empty', async () => {
|
|
335
|
-
const harness = await bootDawn();
|
|
336
|
-
if (harness === null) return;
|
|
337
|
-
const { renderer, device, renderTarget } = harness;
|
|
338
|
-
|
|
339
|
-
let rhiErrors = 0;
|
|
340
|
-
renderer.onError(() => {
|
|
341
|
-
rhiErrors++;
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
const world = new World();
|
|
345
|
-
spawnCubeScene(world);
|
|
346
|
-
|
|
347
|
-
// Drive a single frame through the default pipeline (forgeax::urp),
|
|
348
|
-
// which after M3 is rewritten on top of addColorTarget / addScenePass /
|
|
349
|
-
// addFullscreenPass. The end-to-end signature is observable through pixel
|
|
350
|
-
// readback + perFramePassNames.
|
|
351
|
-
expect(drawPublished(renderer, world).ok).toBe(true);
|
|
352
|
-
await device.queue.onSubmittedWorkDone();
|
|
353
|
-
|
|
354
|
-
// AC-15 / R-PERFPASS: the urp pass names are preserved post-rewrite.
|
|
355
|
-
// perFramePassNames is the machine-readable proof that buildGraph still
|
|
356
|
-
// declares the canonical chain after switching to the public vocabulary.
|
|
357
|
-
//
|
|
358
|
-
// feat-20260613-csm M6 / w22: the legacy 'shadow' pass is now N
|
|
359
|
-
// independent 'shadowCascade<i>' passes (one per cascade tile in the
|
|
360
|
-
// atlas, D-4). Without DirectionalLight with castShadow the urp falls back to
|
|
361
|
-
// cascadeCount=1 -> a single 'shadowCascade0' pass.
|
|
362
|
-
//
|
|
363
|
-
// Point-shadow work and bloom passes are topology-owned: zero point
|
|
364
|
-
// shadows and bloom=off do not declare dead GPU passes. The spot atlas is
|
|
365
|
-
// still cleared once because the main View binding always samples it.
|
|
366
|
-
const expectedPassNames = [
|
|
367
|
-
'directional-shadow-reset',
|
|
368
|
-
'shadowCascade0',
|
|
369
|
-
'directional-shadow-observation',
|
|
370
|
-
'spot-shadow',
|
|
371
|
-
'skybox',
|
|
372
|
-
'main',
|
|
373
|
-
'linear-hdr-observation',
|
|
374
|
-
'output',
|
|
375
|
-
'debug-overlay',
|
|
376
|
-
];
|
|
377
|
-
const passNames = renderer.perFramePassNames;
|
|
378
|
-
expect(passNames).toHaveLength(expectedPassNames.length);
|
|
379
|
-
expect(passNames).toEqual(expect.arrayContaining(expectedPassNames));
|
|
380
|
-
const passIndex = (name: string) => passNames.indexOf(name);
|
|
381
|
-
expect(passIndex('directional-shadow-reset')).toBeLessThan(passIndex('shadowCascade0'));
|
|
382
|
-
expect(passIndex('shadowCascade0')).toBeLessThan(passIndex('directional-shadow-observation'));
|
|
383
|
-
expect(passIndex('directional-shadow-observation')).toBeLessThan(passIndex('main'));
|
|
384
|
-
|
|
385
|
-
// AC-17: read back the swap-chain texture. The cube scene clears to
|
|
386
|
-
// (0.06, 0.06, 0.08) and renders an unlit cube + camera; the readback must
|
|
387
|
-
// contain at least one pixel that differs from the clear colour. If
|
|
388
|
-
// addScenePass / addFullscreenPass were no-ops (the falsifiable case), the
|
|
389
|
-
// entire readback would equal the clear colour and this assertion would
|
|
390
|
-
// fail.
|
|
391
|
-
const bytesPerRow = Math.ceil((WIDTH * 4) / 256) * 256;
|
|
392
|
-
const readback = device.createBuffer({
|
|
393
|
-
size: bytesPerRow * HEIGHT,
|
|
394
|
-
usage: 0x09, // GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
|
|
395
|
-
});
|
|
396
|
-
const cmd = device.createCommandEncoder();
|
|
397
|
-
cmd.copyTextureToBuffer(
|
|
398
|
-
{ texture: renderTarget, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
|
|
399
|
-
{ buffer: readback, bytesPerRow, rowsPerImage: HEIGHT },
|
|
400
|
-
{ width: WIDTH, height: HEIGHT, depthOrArrayLayers: 1 },
|
|
401
|
-
);
|
|
402
|
-
device.queue.submit([cmd.finish()]);
|
|
403
|
-
await readback.mapAsync(1); // GPUMapMode.READ
|
|
404
|
-
const view = new Uint8Array(readback.getMappedRange().slice(0));
|
|
405
|
-
readback.unmap();
|
|
406
|
-
readback.destroy();
|
|
407
|
-
|
|
408
|
-
// Clear colour (0.06, 0.06, 0.08, 1.0) → sRGB-encoded ~ (69, 69, 80) in
|
|
409
|
-
// bgra8unorm-srgb. Find pixels whose channel sum differs from clear by >40
|
|
410
|
-
// (a comfortable threshold for tonemap/fxaa rounding while still proving
|
|
411
|
-
// the scene drew non-clear content).
|
|
412
|
-
const CLEAR_B = 80;
|
|
413
|
-
const CLEAR_G = 69;
|
|
414
|
-
const CLEAR_R = 69;
|
|
415
|
-
let nonClearPixels = 0;
|
|
416
|
-
for (let y = 0; y < HEIGHT; y++) {
|
|
417
|
-
for (let x = 0; x < WIDTH; x++) {
|
|
418
|
-
const off = y * bytesPerRow + x * 4;
|
|
419
|
-
const b = view[off];
|
|
420
|
-
const g = view[off + 1];
|
|
421
|
-
const r = view[off + 2];
|
|
422
|
-
if (b === undefined || g === undefined || r === undefined) continue;
|
|
423
|
-
const delta = Math.abs(b - CLEAR_B) + Math.abs(g - CLEAR_G) + Math.abs(r - CLEAR_R);
|
|
424
|
-
if (delta > 40) nonClearPixels++;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
// AC-17 readback assertion: at least 1% of pixels must differ from the
|
|
428
|
-
// clear colour (a cube + camera fills ~15-30% of the frame; 1% is a very
|
|
429
|
-
// conservative lower bound that still proves the chain end-to-end).
|
|
430
|
-
expect(nonClearPixels).toBeGreaterThan(WIDTH * HEIGHT * 0.01);
|
|
431
|
-
expect(rhiErrors).toBe(0);
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
it('AC-17 falsify: empty scene reads back clear colour (proves end-to-end has discriminating power)', async () => {
|
|
435
|
-
// Falsification anchor for the AC-17 readback above. If the previous test
|
|
436
|
-
// passed only because of leftover GPU state or a dawn quirk (not because
|
|
437
|
-
// addScenePass actually drew the scene), this test would also see
|
|
438
|
-
// non-clear pixels — it doesn't, because spawning no renderables means
|
|
439
|
-
// every pass clears or no-ops, leaving the swap-chain at the clear colour.
|
|
440
|
-
const harness = await bootDawn();
|
|
441
|
-
if (harness === null) return;
|
|
442
|
-
const { renderer, device, renderTarget } = harness;
|
|
443
|
-
|
|
444
|
-
let rhiErrors = 0;
|
|
445
|
-
renderer.onError(() => {
|
|
446
|
-
rhiErrors++;
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
const world = new World();
|
|
450
|
-
// Camera only; NO MeshFilter / MeshRenderer (no draw calls in scene pass).
|
|
451
|
-
world.spawn(
|
|
452
|
-
{
|
|
453
|
-
component: Transform,
|
|
454
|
-
data: {
|
|
455
|
-
pos: [0, 0, 3],
|
|
456
|
-
quat: [0, 0, 0, 1],
|
|
457
|
-
scale: [1, 1, 1],
|
|
458
|
-
},
|
|
459
|
-
},
|
|
460
|
-
// feat-20260608 sibling-collateral: clearColor moved off RendererOptions
|
|
461
|
-
// to the Camera schema (one inline array<f32,4> column as of
|
|
462
|
-
// feat-20260709 M3); explicit values keep this falsify discriminator
|
|
463
|
-
// stable across the surface-trim cut.
|
|
464
|
-
{
|
|
465
|
-
component: Camera,
|
|
466
|
-
data: {
|
|
467
|
-
fov: Math.PI / 4,
|
|
468
|
-
aspect: 1,
|
|
469
|
-
near: 0.1,
|
|
470
|
-
far: 100,
|
|
471
|
-
clearColor: [69 / 255, 69 / 255, 80 / 255, 1],
|
|
472
|
-
},
|
|
473
|
-
},
|
|
474
|
-
);
|
|
475
|
-
|
|
476
|
-
expect(drawPublished(renderer, world).ok).toBe(true);
|
|
477
|
-
await device.queue.onSubmittedWorkDone();
|
|
478
|
-
|
|
479
|
-
const bytesPerRow = Math.ceil((WIDTH * 4) / 256) * 256;
|
|
480
|
-
const readback = device.createBuffer({
|
|
481
|
-
size: bytesPerRow * HEIGHT,
|
|
482
|
-
usage: 0x09, // GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
|
|
483
|
-
});
|
|
484
|
-
const cmd = device.createCommandEncoder();
|
|
485
|
-
cmd.copyTextureToBuffer(
|
|
486
|
-
{ texture: renderTarget, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
|
|
487
|
-
{ buffer: readback, bytesPerRow, rowsPerImage: HEIGHT },
|
|
488
|
-
{ width: WIDTH, height: HEIGHT, depthOrArrayLayers: 1 },
|
|
489
|
-
);
|
|
490
|
-
device.queue.submit([cmd.finish()]);
|
|
491
|
-
await readback.mapAsync(1); // GPUMapMode.READ
|
|
492
|
-
const view = new Uint8Array(readback.getMappedRange().slice(0));
|
|
493
|
-
readback.unmap();
|
|
494
|
-
readback.destroy();
|
|
495
|
-
|
|
496
|
-
// With NO renderables, every pixel should be the clear colour — proving
|
|
497
|
-
// the AC-17 readback test has discriminating power: a regression that
|
|
498
|
-
// dropped scene-draw entirely would surface as "the AC-17 test sees the
|
|
499
|
-
// same clear-only output this test sees".
|
|
500
|
-
// feat-20260608 sibling-collateral: clear color is gamma-encoded by the
|
|
501
|
-
// srgb output view (bgra8unorm-srgb view over bgra8unorm storage), so
|
|
502
|
-
// clearR=clearG=69/255 (=0.27 linear) reads back as ~142 (=0.557 in srgb
|
|
503
|
-
// encoding); clearB=80/255 (=0.314 linear) reads back as ~152.
|
|
504
|
-
const CLEAR_B = 152;
|
|
505
|
-
const CLEAR_G = 142;
|
|
506
|
-
const CLEAR_R = 142;
|
|
507
|
-
let nonClearPixels = 0;
|
|
508
|
-
for (let y = 0; y < HEIGHT; y++) {
|
|
509
|
-
for (let x = 0; x < WIDTH; x++) {
|
|
510
|
-
const off = y * bytesPerRow + x * 4;
|
|
511
|
-
const b = view[off];
|
|
512
|
-
const g = view[off + 1];
|
|
513
|
-
const r = view[off + 2];
|
|
514
|
-
if (b === undefined || g === undefined || r === undefined) continue;
|
|
515
|
-
const delta = Math.abs(b - CLEAR_B) + Math.abs(g - CLEAR_G) + Math.abs(r - CLEAR_R);
|
|
516
|
-
if (delta > 40) nonClearPixels++;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
// Conservative bound: <0.5% of pixels may stray from the clear colour
|
|
520
|
-
// (FXAA edge softening across the 0-pixel boundary, etc.). The difference
|
|
521
|
-
// with AC-17 above (>1% non-clear) is the discriminating signal.
|
|
522
|
-
expect(nonClearPixels).toBeLessThan(WIDTH * HEIGHT * 0.005);
|
|
523
|
-
expect(rhiErrors).toBe(0);
|
|
524
|
-
});
|
|
525
|
-
});
|