@forgeax/engine-render 0.1.20 → 0.1.23
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 +365 -29
- package/dist/assembly/backend-contract.d.ts +13 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/device-feature-admission.d.ts +18 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -0
- package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
- package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +30 -19
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +19 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/render-target-host.d.ts +46 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -0
- package/dist/assets/render-asset-port.d.ts.map +1 -1
- package/dist/authoring.mjs +4 -1
- package/dist/authoring.mjs.map +1 -1
- package/dist/capture/cube-views.d.ts +21 -0
- package/dist/capture/cube-views.d.ts.map +1 -0
- package/dist/capture/scheduler.d.ts +54 -0
- package/dist/capture/scheduler.d.ts.map +1 -0
- package/dist/{chunk-PCHBPYML.mjs → chunk-4L3P6DT5.mjs} +2 -2
- package/dist/chunk-4L3P6DT5.mjs.map +1 -0
- package/dist/{chunk-VFPLTKCU.mjs → chunk-4NPUASZR.mjs} +15 -4
- package/dist/chunk-4NPUASZR.mjs.map +1 -0
- package/dist/chunk-DIYW3M5D.mjs +5085 -0
- package/dist/chunk-DIYW3M5D.mjs.map +1 -0
- package/dist/chunk-FBC4R44J.mjs +1003 -0
- package/dist/chunk-FBC4R44J.mjs.map +1 -0
- package/dist/{chunk-CDTWTHZR.mjs → chunk-FF7K3FSO.mjs} +474 -168
- package/dist/chunk-FF7K3FSO.mjs.map +1 -0
- package/dist/chunk-HZUPSYW7.mjs +1104 -0
- package/dist/chunk-HZUPSYW7.mjs.map +1 -0
- package/dist/{chunk-TBQJOK2L.mjs → chunk-QODA5UKU.mjs} +321 -269
- package/dist/chunk-QODA5UKU.mjs.map +1 -0
- package/dist/chunk-YALPS44A.mjs +296 -0
- package/dist/chunk-YALPS44A.mjs.map +1 -0
- package/dist/{chunk-4XINDLAY.mjs → chunk-ZUWKAZ2I.mjs} +1963 -2178
- package/dist/chunk-ZUWKAZ2I.mjs.map +1 -0
- package/dist/cluster-binner.d.ts +5 -0
- package/dist/cluster-binner.d.ts.map +1 -1
- package/dist/components/camera.d.ts +1 -0
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/cube-camera.d.ts +20 -0
- package/dist/components/cube-camera.d.ts.map +1 -0
- package/dist/components/directional-light.d.ts +11 -2
- package/dist/components/directional-light.d.ts.map +1 -1
- package/dist/components/directional-shadow-filter.d.ts +25 -0
- package/dist/components/directional-shadow-filter.d.ts.map +1 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts +4 -0
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/light-probe.d.ts +9 -0
- package/dist/components/light-probe.d.ts.map +1 -0
- package/dist/components/rect-area-light.d.ts +12 -0
- package/dist/components/rect-area-light.d.ts.map +1 -0
- package/dist/components/reflection-probe.d.ts +17 -0
- package/dist/components/reflection-probe.d.ts.map +1 -0
- package/dist/components/scene-instance.d.ts +4 -0
- package/dist/components/scene-instance.d.ts.map +1 -1
- package/dist/components/spot-light.d.ts +3 -0
- package/dist/components/spot-light.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +14836 -9620
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +8 -1
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/device/lifecycle-transaction.d.ts +2 -0
- package/dist/device/lifecycle-transaction.d.ts.map +1 -0
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +5 -0
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/gpu-driven.d.ts +26 -0
- package/dist/errors/gpu-driven.d.ts.map +1 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +9 -1
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +166 -93
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/directional-shadow-projection.d.ts +23 -0
- package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
- package/dist/extract/environment.d.ts +14 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +50 -0
- package/dist/extract/gpu-driven.d.ts.map +1 -0
- package/dist/extract/visibility.d.ts.map +1 -1
- package/dist/features/fullscreen.d.ts.map +1 -1
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +10 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +13 -2
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +34 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts +63 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +97 -2
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/view-gpu.d.ts +64 -1
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts +14 -0
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +8 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-usage.d.ts +0 -1
- package/dist/gpu-usage.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +21 -19
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +4 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/kernel-cache.d.ts +36 -0
- package/dist/ibl/kernel-cache.d.ts.map +1 -0
- package/dist/index.d.ts +39 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +91 -6
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +214 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances-derived-bounds.d.ts +50 -0
- package/dist/instances-derived-bounds.d.ts.map +1 -0
- package/dist/internal.d.ts +9 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +23 -2
- package/dist/internal.mjs.map +1 -1
- package/dist/light-buffer-layout.d.ts +58 -140
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +54 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +38 -14
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts +2 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
- package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
- package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
- package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
- package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
- package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
- package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts +4 -13
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline/standard-profile.d.ts +5 -26
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +2 -0
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +40 -7
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/point-shadow-inspection.d.ts +21 -0
- package/dist/point-shadow-inspection.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
- package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/resources.d.ts +72 -0
- package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/state.d.ts +24 -0
- package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +33 -36
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +78 -24
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts +5 -0
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +16 -6
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
- package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
- package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/index.d.ts +8 -0
- package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
- package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/session.d.ts +43 -0
- package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +20 -3
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +0 -20
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +6 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +25 -2
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +98 -6
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +119 -4
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +7 -5
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/reflection/filter.d.ts +22 -0
- package/dist/reflection/filter.d.ts.map +1 -0
- package/dist/reflection/gpu-table.d.ts +25 -0
- package/dist/reflection/gpu-table.d.ts.map +1 -0
- package/dist/reflection/inspection.d.ts +10 -0
- package/dist/reflection/inspection.d.ts.map +1 -0
- package/dist/reflection/projection.d.ts +140 -0
- package/dist/reflection/projection.d.ts.map +1 -0
- package/dist/reflection/record-owner.d.ts +60 -0
- package/dist/reflection/record-owner.d.ts.map +1 -0
- package/dist/render-contract.d.ts +62 -14
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +1 -0
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +49 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +160 -31
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +28 -2
- package/dist/render-system.d.ts.map +1 -1
- package/dist/renderer.d.ts +43 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/scene/probe-blend-record.d.ts +22 -0
- package/dist/scene/probe-blend-record.d.ts.map +1 -0
- package/dist/scene/probe-blend.d.ts +142 -0
- package/dist/scene/probe-blend.d.ts.map +1 -0
- package/dist/scene/render-scene-types.d.ts +0 -6
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +117 -9
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/visibility/bounds.d.ts +20 -0
- package/dist/scene/visibility/bounds.d.ts.map +1 -0
- package/dist/scene/visibility/budget.d.ts +16 -0
- package/dist/scene/visibility/budget.d.ts.map +1 -0
- package/dist/scene/visibility/facet.d.ts +73 -0
- package/dist/scene/visibility/facet.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-lod.d.ts +46 -0
- package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
- package/dist/scene/visibility/inspection.d.ts +132 -0
- package/dist/scene/visibility/inspection.d.ts.map +1 -0
- package/dist/scene/visibility/lod-selector.d.ts +25 -0
- package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
- package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
- package/dist/scene/visibility/types.d.ts +34 -0
- package/dist/scene/visibility/types.d.ts.map +1 -0
- package/dist/shadow-atlas.d.ts +3 -3
- package/dist/shadow-atlas.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +3 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/ssr/admission.d.ts +122 -0
- package/dist/ssr/admission.d.ts.map +1 -0
- package/dist/ssr/composition.d.ts +32 -0
- package/dist/ssr/composition.d.ts.map +1 -0
- package/dist/ssr/errors.d.ts +39 -0
- package/dist/ssr/errors.d.ts.map +1 -0
- package/dist/ssr/identity.d.ts +13 -0
- package/dist/ssr/identity.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +1 -1
- package/dist/targets/contracts.d.ts +66 -0
- package/dist/targets/contracts.d.ts.map +1 -0
- package/dist/targets/graph-projection.d.ts +29 -0
- package/dist/targets/graph-projection.d.ts.map +1 -0
- package/dist/targets/material-source.d.ts +34 -0
- package/dist/targets/material-source.d.ts.map +1 -0
- package/dist/targets/owner.d.ts +32 -0
- package/dist/targets/owner.d.ts.map +1 -0
- package/dist/targets/physical.d.ts +18 -0
- package/dist/targets/physical.d.ts.map +1 -0
- package/dist/targets/readback.d.ts +39 -0
- package/dist/targets/readback.d.ts.map +1 -0
- package/dist/temporal/frame-coordinator.d.ts +13 -0
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +2 -0
- package/dist/temporal/frame.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -5
- package/dist/temporal/view.d.ts +7 -0
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/tilemap-chunk-extract-system.d.ts +1 -1
- package/dist/typed-render-graph-primitives.d.ts +5 -1
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +1 -1
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +9 -5
- package/dist/volume/passes.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
- package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
- package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
- package/src/__tests__/cluster-binner.unit.test.ts +35 -0
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +12 -2
- package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
- package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
- package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
- package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
- package/src/__tests__/cube-camera.integration.test.ts +42 -0
- package/src/__tests__/detached-inspection.integration.test.ts +6 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +85 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +62 -6
- package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
- package/src/__tests__/environment-generation.integration.test.ts +16 -0
- package/src/__tests__/evidence-identity.ts +13 -0
- package/src/__tests__/evidence-identity.unit.test.ts +24 -0
- package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
- package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
- package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
- package/src/__tests__/factory-contract.integration.test.ts +288 -29
- package/src/__tests__/fog-component.unit.test.ts +67 -0
- package/src/__tests__/fog.integration.test.ts +86 -0
- package/src/__tests__/frame-observation.contract.test.ts +15 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -8
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +18 -1
- package/src/__tests__/gpu-driven-production.integration.test.ts +579 -17
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +101 -6
- package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
- package/src/__tests__/gpu-lod-evidence.ts +188 -0
- package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
- package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
- package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
- package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
- package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
- package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
- package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
- package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
- package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
- package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
- package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
- package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
- package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
- package/src/__tests__/gpu-scene.unit.test.ts +49 -3
- package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
- package/src/__tests__/instances-culling.integration.test.ts +94 -0
- package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
- package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
- package/src/__tests__/light-inspection.unit.test.ts +55 -0
- package/src/__tests__/light-resource-error.unit.test.ts +43 -0
- package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
- package/src/__tests__/lod-bounds.unit.test.ts +42 -0
- package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
- package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
- package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
- package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
- package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
- package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
- package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
- package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
- package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
- package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
- package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
- package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
- package/src/__tests__/lod-selector.profile.test.ts +35 -0
- package/src/__tests__/lod-selector.unit.test.ts +68 -0
- package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
- package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
- package/src/__tests__/ltc-resources.unit.test.ts +32 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +17 -0
- package/src/__tests__/material-observation.integration.test.ts +101 -0
- package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
- package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
- package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
- package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
- package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
- package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
- package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
- package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
- package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
- package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
- package/src/__tests__/occlusion-query.evidence.ts +178 -0
- package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
- package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
- package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
- package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
- package/src/__tests__/probe-bindings.unit.test.ts +200 -0
- package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
- package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
- package/src/__tests__/probe-capacity.integration.test.ts +97 -0
- package/src/__tests__/probe-recovery.integration.test.ts +104 -0
- package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
- package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
- package/src/__tests__/profiler-phase-token.test.ts +1 -0
- package/src/__tests__/public-surface.test-d.ts +10 -0
- package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
- package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
- package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
- package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
- package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
- package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
- package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
- package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
- package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
- package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
- package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
- package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +19 -3
- package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
- package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
- package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
- package/src/__tests__/render-target-admission.unit.test.ts +80 -0
- package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
- package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
- package/src/__tests__/render-target-material-source.test-d.ts +30 -0
- package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
- package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
- package/src/__tests__/render-target-owner.unit.test.ts +122 -0
- package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
- package/src/__tests__/render-target-public-schema.json +107 -0
- package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
- package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
- package/src/__tests__/render-target-readback.integration.test.ts +90 -0
- package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +124 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
- package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
- package/src/__tests__/skin-motion-regression.unit.test.ts +154 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +13 -4
- package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
- package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
- package/src/__tests__/ssr-composition.unit.test.ts +46 -0
- package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
- package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
- package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
- package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +299 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +15 -5
- package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
- package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
- package/src/__tests__/standard-lighting-write.unit.test.ts +441 -0
- package/src/__tests__/standard-lighting.integration.test.ts +67 -0
- package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
- package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
- package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
- package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -38
- package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
- package/src/__tests__/temporal-view.unit.test.ts +3 -3
- package/src/__tests__/transmission-prewarm.unit.test.ts +69 -0
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
- package/src/__tests__/visibility-budget.integration.test.ts +140 -0
- package/src/__tests__/visibility-budget.unit.test.ts +70 -0
- package/src/__tests__/visibility-extract.integration.test.ts +11 -6
- package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
- package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
- package/src/assembly/backend-contract.ts +13 -0
- package/src/assembly/device-feature-admission.ts +80 -0
- package/src/assembly/directional-shadow-inspection.ts +122 -0
- package/src/assembly/factory.ts +1411 -366
- package/src/assembly/host-contract.ts +35 -0
- package/src/assembly/render-target-host.ts +847 -0
- package/src/assets/asset-decoders.ts +1 -1
- package/src/assets/render-asset-port.ts +7 -1
- package/src/capture/cube-views.ts +69 -0
- package/src/capture/scheduler.ts +265 -0
- package/src/cluster-binner.ts +31 -0
- package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
- package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
- package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
- package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
- package/src/components/camera.ts +4 -0
- package/src/components/cube-camera.ts +52 -0
- package/src/components/directional-light.ts +22 -2
- package/src/components/directional-shadow-filter.ts +57 -0
- package/src/components/index.ts +5 -0
- package/src/components/light-helpers.ts +133 -8
- package/src/components/light-probe.ts +13 -0
- package/src/components/rect-area-light.ts +15 -0
- package/src/components/reflection-probe.ts +49 -0
- package/src/components/scene-instance.ts +6 -0
- package/src/components/spot-light.ts +3 -0
- package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
- package/src/device/gpu-residency.ts +140 -9
- package/src/device/lifecycle-transaction.ts +12 -0
- package/src/environment/frame.ts +6 -24
- package/src/environment/lifecycle.ts +20 -1
- package/src/errors/gpu-driven.ts +92 -0
- package/src/errors/index.ts +1 -0
- package/src/errors/recover.ts +32 -0
- package/src/errors/render.ts +341 -143
- package/src/extract/camera.ts +3 -3
- package/src/extract/directional-shadow-projection.ts +61 -0
- package/src/extract/environment.ts +57 -0
- package/src/extract/gpu-driven.ts +108 -0
- package/src/extract/visibility.ts +2 -1
- package/src/features/fullscreen.ts +3 -0
- package/src/features/targets.ts +4 -1
- package/src/features/types.ts +10 -0
- package/src/fullscreen-post-process-pass.ts +43 -2
- package/src/gpu-driven/batch-topology.ts +207 -28
- package/src/gpu-driven/prepared-draw.ts +208 -0
- package/src/gpu-driven/production-raster.ts +953 -43
- package/src/gpu-driven/view-gpu.ts +411 -29
- package/src/gpu-scene-schema.ts +13 -0
- package/src/gpu-scene.ts +140 -64
- package/src/gpu-usage.ts +0 -1
- package/src/hdrp-buffers.ts +169 -63
- package/src/ibl/IblPipelineCache.ts +11 -0
- package/src/ibl/kernel-cache.ts +88 -0
- package/src/index.ts +222 -0
- package/src/inspection-types.ts +276 -1
- package/src/instances-derived-bounds.ts +171 -0
- package/src/internal.ts +38 -0
- package/src/light-buffer-layout.ts +155 -310
- package/src/materials.ts +16 -2
- package/src/mesh-material-bindings.ts +132 -0
- package/src/pbr-pipeline.ts +255 -60
- package/src/pipeline/standard-forward-lane.ts +93 -16
- package/src/pipeline/standard-lighting/errors.ts +6 -0
- package/src/pipeline/standard-lighting/graph.ts +158 -0
- package/src/pipeline/standard-lighting/inspection.ts +88 -0
- package/src/pipeline/standard-lighting/layout.ts +31 -0
- package/src/pipeline/standard-lighting/light-frame.ts +35 -0
- package/src/pipeline/standard-lighting/membership.ts +43 -0
- package/src/pipeline/standard-lighting/prepare.ts +37 -0
- package/src/pipeline/standard-lighting/topology.ts +120 -0
- package/src/pipeline/standard-lighting/transport.ts +78 -0
- package/src/pipeline/standard-pipeline.ts +124 -193
- package/src/pipeline/standard-post.ts +26 -7
- package/src/pipeline/standard-profile.ts +17 -47
- package/src/pipeline-builder.ts +5 -2
- package/src/pipeline-spec.ts +95 -21
- package/src/plugin.ts +4 -0
- package/src/point-shadow-inspection.ts +55 -0
- package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
- package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
- package/src/prepare/extended-lighting/resources.ts +389 -0
- package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
- package/src/prepare/extended-lighting/state.ts +92 -0
- package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
- package/src/record/__tests__/temporal-payload.unit.test.ts +64 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
- package/src/record/frame-lighting.ts +591 -452
- package/src/record/frame-snapshot.ts +92 -39
- package/src/record/frame-targets.ts +17 -0
- package/src/record/frame.ts +662 -158
- package/src/record/gpu-pass-timing/contract.ts +180 -0
- package/src/record/gpu-pass-timing/errors.ts +34 -0
- package/src/record/gpu-pass-timing/index.ts +37 -0
- package/src/record/gpu-pass-timing/parser.ts +97 -0
- package/src/record/gpu-pass-timing/session.ts +938 -0
- package/src/record/gpu-timing.ts +112 -39
- package/src/record/helpers.ts +0 -58
- package/src/record/main-pass-geometry.ts +324 -119
- package/src/record/main-pass-material.ts +103 -10
- package/src/record/main-pass-sprite-draws.ts +99 -103
- package/src/record/main-pass.ts +71 -15
- package/src/record/mesh-ssbo.ts +47 -36
- package/src/record/render-context.ts +136 -3
- package/src/record/shadow-pass.ts +83 -68
- package/src/record/skybox-post-pass.ts +20 -4
- package/src/record/typed-frame-graph.ts +1034 -43
- package/src/record/view-ubo.ts +72 -47
- package/src/reflection/filter.ts +81 -0
- package/src/reflection/gpu-table.ts +44 -0
- package/src/reflection/inspection.ts +67 -0
- package/src/reflection/projection.ts +476 -0
- package/src/reflection/record-owner.ts +1283 -0
- package/src/render-contract.ts +93 -10
- package/src/render-graph-primitives.ts +9 -4
- package/src/render-pipeline.ts +122 -2
- package/src/render-system-extract.ts +1041 -225
- package/src/render-system.ts +1310 -85
- package/src/renderer.ts +222 -0
- package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
- package/src/scene/probe-blend-record.ts +54 -0
- package/src/scene/probe-blend.ts +813 -0
- package/src/scene/render-scene-types.ts +0 -7
- package/src/scene/render-scene.ts +942 -171
- package/src/scene/visibility/bounds.ts +57 -0
- package/src/scene/visibility/budget.ts +40 -0
- package/src/scene/visibility/facet.ts +400 -0
- package/src/scene/visibility/gpu-frame-timing.ts +101 -0
- package/src/scene/visibility/gpu-lod.ts +119 -0
- package/src/scene/visibility/inspection.ts +313 -0
- package/src/scene/visibility/lod-selector.ts +84 -0
- package/src/scene/visibility/occlusion-confidence.ts +478 -0
- package/src/scene/visibility/occlusion-pass.ts +165 -0
- package/src/scene/visibility/occlusion-query-pool.ts +178 -0
- package/src/scene/visibility/occlusion-runtime.ts +672 -0
- package/src/scene/visibility/types.ts +50 -0
- package/src/shadow-atlas.ts +5 -5
- package/src/ssao-buffers.ts +9 -2
- package/src/ssr/admission.ts +451 -0
- package/src/ssr/composition.ts +73 -0
- package/src/ssr/errors.ts +76 -0
- package/src/ssr/identity.ts +12 -0
- package/src/systems/skin-palette-allocator.ts +1 -1
- package/src/targets/contracts.ts +182 -0
- package/src/targets/graph-projection.ts +169 -0
- package/src/targets/material-source.ts +143 -0
- package/src/targets/owner.ts +214 -0
- package/src/targets/physical.ts +18 -0
- package/src/targets/readback.ts +153 -0
- package/src/temporal/frame-coordinator.ts +26 -0
- package/src/temporal/frame.ts +14 -1
- package/src/temporal/view.ts +11 -0
- package/src/tilemap-chunk-extract-system.ts +4 -4
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
- package/src/typed-render-graph-primitives.ts +53 -3
- package/src/typed-shadow-passes.ts +46 -40
- package/src/volume/passes.ts +61 -58
- package/dist/.tsbuildinfo +0 -1
- package/dist/chunk-4XINDLAY.mjs.map +0 -1
- package/dist/chunk-CDTWTHZR.mjs.map +0 -1
- package/dist/chunk-M2MP4ZOU.mjs +0 -73
- package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
- package/dist/chunk-PCHBPYML.mjs.map +0 -1
- package/dist/chunk-TBQJOK2L.mjs.map +0 -1
- package/dist/chunk-VFPLTKCU.mjs.map +0 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Closed view roles used by the renderer-owned visibility facet. */
|
|
2
|
+
export type VisibilityViewRole = 'main' | 'shadow' | 'reflection' | 'probe';
|
|
3
|
+
|
|
4
|
+
export interface ViewKey {
|
|
5
|
+
readonly attachmentId: string;
|
|
6
|
+
readonly cameraEntity: number;
|
|
7
|
+
readonly viewRole: VisibilityViewRole;
|
|
8
|
+
readonly viewGeneration: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface PrimitiveKey {
|
|
12
|
+
readonly attachmentId: string;
|
|
13
|
+
readonly worldGeneration: number;
|
|
14
|
+
readonly primitiveSlot: number;
|
|
15
|
+
readonly slotGeneration: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface VisibilityCandidate {
|
|
19
|
+
readonly level: number;
|
|
20
|
+
readonly confidence: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface VisibilityFacetInspection {
|
|
24
|
+
readonly owner: 'persistent-render-scene';
|
|
25
|
+
readonly activeViews: number;
|
|
26
|
+
readonly facetRows: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface VisibilityFacetInput {
|
|
30
|
+
readonly view: ViewKey;
|
|
31
|
+
readonly primitive: PrimitiveKey;
|
|
32
|
+
readonly epoch: number;
|
|
33
|
+
readonly candidate: VisibilityCandidate;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function viewKeyId(key: ViewKey): string {
|
|
37
|
+
return `${key.attachmentId}:${key.cameraEntity}:${key.viewRole}:${key.viewGeneration}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function primitiveKeyId(key: PrimitiveKey): string {
|
|
41
|
+
return `${key.attachmentId}:${key.worldGeneration}:${key.primitiveSlot}:${key.slotGeneration}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function viewKey(input: ViewKey): ViewKey {
|
|
45
|
+
return Object.freeze({ ...input });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function primitiveKey(input: PrimitiveKey): PrimitiveKey {
|
|
49
|
+
return Object.freeze({ ...input });
|
|
50
|
+
}
|
package/src/shadow-atlas.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// feat-20260612-point-light-shadows-urp-hdrp M3 / T-M3-1 (plan-strategy §D-1).
|
|
4
4
|
//
|
|
5
5
|
// Lazy-allocated `texture_depth_cube_array` (depth32float) + per-face 2D
|
|
6
|
-
// TextureView cache. One layer per shadow-casting PointLight
|
|
7
|
-
//
|
|
6
|
+
// TextureView cache. One layer per admitted shadow-casting PointLight; the
|
|
7
|
+
// renderer owns the bounded atlas admission policy. Total texel footprint at
|
|
8
8
|
// the 512x512 default = 4 layers x 6 faces x 512 x 512 x 4 B = 24 MiB.
|
|
9
9
|
//
|
|
10
10
|
// Why a separate module (vs inlining into createRenderer / pipelineState):
|
|
@@ -53,19 +53,19 @@ import { GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING } from './gpu-t
|
|
|
53
53
|
export interface ShadowAtlasOptions {
|
|
54
54
|
/** Per-face square size in pixels. Default 512 (PointLightShadow.mapSize default). */
|
|
55
55
|
readonly faceSize?: number;
|
|
56
|
-
/** Number of cube layers. Default
|
|
56
|
+
/** Number of cube layers. Default is the renderer atlas admission capacity. */
|
|
57
57
|
readonly layers?: number;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/** Default per-face square size in pixels. Mirrors PointLightShadow.mapSize default. */
|
|
61
61
|
export const SHADOW_ATLAS_DEFAULT_FACE_SIZE = 512;
|
|
62
|
-
/** Default cube layer count.
|
|
62
|
+
/** Default cube layer count. Renderer-owned point-shadow admission capacity. */
|
|
63
63
|
export const SHADOW_ATLAS_DEFAULT_LAYERS = 4;
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Cube-array depth atlas for point-light shadows.
|
|
67
67
|
*
|
|
68
|
-
* Shape: `texture_depth_cube_array` (depth32float) with `layers
|
|
68
|
+
* Shape: `texture_depth_cube_array` (depth32float) with `layers` and per-
|
|
69
69
|
* face size `faceSize x faceSize`. The cube_array sampling view feeds
|
|
70
70
|
* `@group(0) @binding(5)` in URP shaders; the per-face 2D view feeds the
|
|
71
71
|
* shadow-caster render pass attachment for one (layer, face) at a time
|
package/src/ssao-buffers.ts
CHANGED
|
@@ -106,6 +106,7 @@ export const SSAO_UNIFORM_BYTES = UNIFORM_BYTES;
|
|
|
106
106
|
// recompile across enable/disable.
|
|
107
107
|
|
|
108
108
|
interface SsaoFallbackResources {
|
|
109
|
+
readonly device: RenderSystemRuntime['device'];
|
|
109
110
|
readonly texture: Texture;
|
|
110
111
|
readonly view: TextureView;
|
|
111
112
|
readonly sampler: Sampler;
|
|
@@ -126,7 +127,8 @@ export function getOrCreateSsaoFallbackTexture(
|
|
|
126
127
|
runtime: RenderSystemRuntime,
|
|
127
128
|
): SsaoFallbackResources | null {
|
|
128
129
|
const cached = fallbackCache.get(runtime);
|
|
129
|
-
if (cached !== undefined) return cached;
|
|
130
|
+
if (cached !== undefined && cached.device === runtime.device) return cached;
|
|
131
|
+
if (cached !== undefined) fallbackCache.delete(runtime);
|
|
130
132
|
|
|
131
133
|
const device = runtime.device;
|
|
132
134
|
const texRes = device.createTexture({
|
|
@@ -191,6 +193,7 @@ export function getOrCreateSsaoFallbackTexture(
|
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
const resources: SsaoFallbackResources = {
|
|
196
|
+
device,
|
|
194
197
|
texture: texRes.value,
|
|
195
198
|
view: viewRes.value,
|
|
196
199
|
sampler: samplerRes.value,
|
|
@@ -205,6 +208,8 @@ export function getOrCreateSsaoFallbackTexture(
|
|
|
205
208
|
* Fields are readonly per charter P5: one resource, one owner.
|
|
206
209
|
*/
|
|
207
210
|
export interface SsaoBuffers {
|
|
211
|
+
/** Device identity that owns every handle in this bundle. */
|
|
212
|
+
readonly device: RenderSystemRuntime['device'];
|
|
208
213
|
/** 64 padded vec4 uniform buffer for hemisphere samples. */
|
|
209
214
|
readonly kernelBuffer: Buffer;
|
|
210
215
|
readonly kernelBytes: number;
|
|
@@ -229,7 +234,8 @@ const cache = new WeakMap<RenderSystemRuntime, SsaoBuffers>();
|
|
|
229
234
|
*/
|
|
230
235
|
export function getOrCreateSsaoBuffers(runtime: RenderSystemRuntime): SsaoBuffers | null {
|
|
231
236
|
const cached = cache.get(runtime);
|
|
232
|
-
if (cached !== undefined) return cached;
|
|
237
|
+
if (cached !== undefined && cached.device === runtime.device) return cached;
|
|
238
|
+
if (cached !== undefined) cache.delete(runtime);
|
|
233
239
|
|
|
234
240
|
const device = runtime.device;
|
|
235
241
|
|
|
@@ -322,6 +328,7 @@ export function getOrCreateSsaoBuffers(runtime: RenderSystemRuntime): SsaoBuffer
|
|
|
322
328
|
}
|
|
323
329
|
|
|
324
330
|
const buffers: SsaoBuffers = {
|
|
331
|
+
device,
|
|
325
332
|
kernelBuffer: kernelBufferRes.value,
|
|
326
333
|
kernelBytes: SSAO_KERNEL_SAMPLE_COUNT * BYTES_PER_KERNEL_ELEMENT,
|
|
327
334
|
noiseTexture: noiseTexRes.value,
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consumer-only SSR M0 admission.
|
|
3
|
+
*
|
|
4
|
+
* This module consumes detached producer receipts. It owns no capture,
|
|
5
|
+
* device, graph, or recovery handle and therefore cannot repair a missing
|
|
6
|
+
* producer. A complete receipt set is the only route to an admitted result.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
type RhiTextureFormatCapabilityReceipt,
|
|
11
|
+
validateR32FloatReceipt,
|
|
12
|
+
} from '@forgeax/engine-rhi';
|
|
13
|
+
import type { ReflectionFallbackReceipt } from '../inspection-types';
|
|
14
|
+
import type { SsrOwnerRecoveryAction } from './errors';
|
|
15
|
+
import type { SsrAdmissionIdentity } from './identity';
|
|
16
|
+
|
|
17
|
+
export const SSR_FORMAT_PROFILE = 'r32float-mip-sampled-storage' as const;
|
|
18
|
+
|
|
19
|
+
export const SSR_FORMAT_STAGES = Object.freeze([
|
|
20
|
+
'texture-create',
|
|
21
|
+
'mip-view',
|
|
22
|
+
'sampled-storage-bind-group',
|
|
23
|
+
'pipeline-bind',
|
|
24
|
+
'finish',
|
|
25
|
+
'submit',
|
|
26
|
+
'completion',
|
|
27
|
+
'readback',
|
|
28
|
+
] as const);
|
|
29
|
+
|
|
30
|
+
export type { SsrAdmissionIdentity } from './identity';
|
|
31
|
+
|
|
32
|
+
export type SsrFormatStage = (typeof SSR_FORMAT_STAGES)[number];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The admission input is the real renderer owner receipt plus the one
|
|
36
|
+
* integration identity supplied by the host. It deliberately does not
|
|
37
|
+
* recreate submitted/source/LKG boolean flags.
|
|
38
|
+
*/
|
|
39
|
+
export type SsrReflectionFallbackReceipt = ReflectionFallbackReceipt & {
|
|
40
|
+
readonly identity: SsrAdmissionIdentity;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/** RHI capability receipt with the same host-supplied integration identity. */
|
|
44
|
+
export type SsrFormatReceipt = RhiTextureFormatCapabilityReceipt & {
|
|
45
|
+
readonly identity: SsrAdmissionIdentity;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export interface SsrTemporalReceipt {
|
|
49
|
+
readonly identity: SsrAdmissionIdentity;
|
|
50
|
+
readonly successfulSubmit: true;
|
|
51
|
+
readonly generation: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface SsrAdmissionWork {
|
|
55
|
+
readonly attachmentCount: number;
|
|
56
|
+
readonly passCount: number;
|
|
57
|
+
readonly bindingCount: number;
|
|
58
|
+
readonly resourceCount: number;
|
|
59
|
+
readonly historyCount: 0;
|
|
60
|
+
readonly temporalDemand: 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface SsrAdmissionBudget {
|
|
64
|
+
readonly probeExecutions: 0 | 1;
|
|
65
|
+
readonly resetCount: 0;
|
|
66
|
+
readonly rebuildCount: 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface SsrAdmissionFailure {
|
|
70
|
+
readonly code:
|
|
71
|
+
| 'ssr-not-requested'
|
|
72
|
+
| 'ssr-reflection-fallback-unavailable'
|
|
73
|
+
| 'ssr-format-unavailable'
|
|
74
|
+
| 'ssr-temporal-unavailable'
|
|
75
|
+
| 'ssr-receipt-identity-mismatch'
|
|
76
|
+
| 'ssr-receipt-stale';
|
|
77
|
+
readonly expected: string;
|
|
78
|
+
readonly hint: string;
|
|
79
|
+
readonly detail: Readonly<{
|
|
80
|
+
readonly owner: 'producer' | 'format' | 'temporal' | 'consumer';
|
|
81
|
+
/** Owner-directed action an AI consumer can take without parsing hint text. */
|
|
82
|
+
readonly action: SsrOwnerRecoveryAction;
|
|
83
|
+
readonly generation?: number;
|
|
84
|
+
readonly identityField?: keyof SsrAdmissionIdentity;
|
|
85
|
+
}>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type SsrAdmissionResult =
|
|
89
|
+
| {
|
|
90
|
+
readonly status: 'admitted';
|
|
91
|
+
readonly identity: SsrAdmissionIdentity | undefined;
|
|
92
|
+
readonly generation: number;
|
|
93
|
+
readonly work: SsrAdmissionWork;
|
|
94
|
+
readonly budget: SsrAdmissionBudget;
|
|
95
|
+
readonly failure?: undefined;
|
|
96
|
+
}
|
|
97
|
+
| {
|
|
98
|
+
readonly status: 'fallback-only';
|
|
99
|
+
readonly identity: SsrAdmissionIdentity | undefined;
|
|
100
|
+
readonly generation: number;
|
|
101
|
+
readonly work: SsrAdmissionWork;
|
|
102
|
+
readonly budget: SsrAdmissionBudget;
|
|
103
|
+
readonly failure: SsrAdmissionFailure;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export interface SsrAdmissionInput {
|
|
107
|
+
readonly requested: boolean;
|
|
108
|
+
readonly identity: SsrAdmissionIdentity;
|
|
109
|
+
readonly reflectionFallback?: SsrReflectionFallbackReceipt;
|
|
110
|
+
readonly format?: SsrFormatReceipt;
|
|
111
|
+
readonly temporal?: SsrTemporalReceipt;
|
|
112
|
+
readonly previousGeneration?: number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Public renderer projection consumed by the parent SSR feature. */
|
|
116
|
+
export interface SsrDependenciesInspection {
|
|
117
|
+
readonly status: 'admitted' | 'fallback-only';
|
|
118
|
+
/** Absent until the host binds an exact source/tree/lock/build identity. */
|
|
119
|
+
readonly identity: SsrAdmissionIdentity | undefined;
|
|
120
|
+
readonly requested: boolean;
|
|
121
|
+
readonly reflectionFallback: ReflectionFallbackReceipt | undefined;
|
|
122
|
+
readonly format: SsrFormatReceipt | undefined;
|
|
123
|
+
readonly temporal: SsrTemporalReceipt | undefined;
|
|
124
|
+
readonly admission: SsrAdmissionResult;
|
|
125
|
+
readonly work: SsrAdmissionWork;
|
|
126
|
+
readonly budget: SsrAdmissionBudget;
|
|
127
|
+
readonly failure: SsrAdmissionFailure | undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const ZERO_WORK: SsrAdmissionWork = Object.freeze({
|
|
131
|
+
attachmentCount: 0,
|
|
132
|
+
passCount: 0,
|
|
133
|
+
bindingCount: 0,
|
|
134
|
+
resourceCount: 0,
|
|
135
|
+
historyCount: 0,
|
|
136
|
+
temporalDemand: 0,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const ADMITTED_WORK: SsrAdmissionWork = Object.freeze({
|
|
140
|
+
attachmentCount: 1,
|
|
141
|
+
passCount: 1,
|
|
142
|
+
bindingCount: 1,
|
|
143
|
+
resourceCount: 1,
|
|
144
|
+
historyCount: 0,
|
|
145
|
+
temporalDemand: 0,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const ZERO_BUDGET: SsrAdmissionBudget = Object.freeze({
|
|
149
|
+
probeExecutions: 0,
|
|
150
|
+
resetCount: 0,
|
|
151
|
+
rebuildCount: 0,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const ADMITTED_BUDGET: SsrAdmissionBudget = Object.freeze({
|
|
155
|
+
probeExecutions: 1,
|
|
156
|
+
resetCount: 0,
|
|
157
|
+
rebuildCount: 0,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
function identityFieldMismatch(
|
|
161
|
+
expected: SsrAdmissionIdentity,
|
|
162
|
+
actual: SsrAdmissionIdentity,
|
|
163
|
+
): keyof SsrAdmissionIdentity | undefined {
|
|
164
|
+
for (const field of ['sourceHead', 'sourceTree', 'lockSha256', 'buildSha256'] as const) {
|
|
165
|
+
if (expected[field] !== actual[field]) return field;
|
|
166
|
+
}
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function blocked(
|
|
171
|
+
identity: SsrAdmissionIdentity | undefined,
|
|
172
|
+
failure: SsrAdmissionFailure,
|
|
173
|
+
generation = 0,
|
|
174
|
+
): SsrAdmissionResult {
|
|
175
|
+
return Object.freeze({
|
|
176
|
+
status: 'fallback-only',
|
|
177
|
+
identity,
|
|
178
|
+
generation,
|
|
179
|
+
work: ZERO_WORK,
|
|
180
|
+
budget: ZERO_BUDGET,
|
|
181
|
+
failure,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function failure(
|
|
186
|
+
code: SsrAdmissionFailure['code'],
|
|
187
|
+
owner: SsrAdmissionFailure['detail']['owner'],
|
|
188
|
+
hint: string,
|
|
189
|
+
detail: Omit<SsrAdmissionFailure['detail'], 'owner' | 'action'> = {},
|
|
190
|
+
): SsrAdmissionFailure {
|
|
191
|
+
const action: SsrOwnerRecoveryAction = recoveryActionFor(code);
|
|
192
|
+
return Object.freeze({
|
|
193
|
+
code,
|
|
194
|
+
expected: 'all producer, format, and temporal receipts share one admitted identity',
|
|
195
|
+
hint,
|
|
196
|
+
detail: Object.freeze({ owner, action, ...detail }),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function recoveryActionFor(code: SsrAdmissionFailure['code']): SsrOwnerRecoveryAction {
|
|
201
|
+
switch (code) {
|
|
202
|
+
case 'ssr-reflection-fallback-unavailable':
|
|
203
|
+
case 'ssr-receipt-identity-mismatch':
|
|
204
|
+
return 'rebuild';
|
|
205
|
+
case 'ssr-not-requested':
|
|
206
|
+
case 'ssr-format-unavailable':
|
|
207
|
+
case 'ssr-temporal-unavailable':
|
|
208
|
+
case 'ssr-receipt-stale':
|
|
209
|
+
return 'retry';
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function receiptFailure(
|
|
214
|
+
input: SsrAdmissionInput,
|
|
215
|
+
receipt: { readonly identity: SsrAdmissionIdentity },
|
|
216
|
+
owner: SsrAdmissionFailure['detail']['owner'],
|
|
217
|
+
): SsrAdmissionResult | undefined {
|
|
218
|
+
const field = identityFieldMismatch(input.identity, receipt.identity);
|
|
219
|
+
if (field === undefined) return undefined;
|
|
220
|
+
return blocked(
|
|
221
|
+
input.identity,
|
|
222
|
+
failure('ssr-receipt-identity-mismatch', owner, 'rebuild the owner receipt for this identity', {
|
|
223
|
+
identityField: field,
|
|
224
|
+
}),
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function validFallback(receipt: SsrReflectionFallbackReceipt | undefined): boolean {
|
|
229
|
+
return (
|
|
230
|
+
receipt !== undefined &&
|
|
231
|
+
receipt.candidateVisible === false &&
|
|
232
|
+
Number.isFinite(receipt.coverage) &&
|
|
233
|
+
receipt.coverage >= 0 &&
|
|
234
|
+
receipt.coverage <= 1 &&
|
|
235
|
+
(receipt.sourceKey === undefined || receipt.sourceKey.length > 0) &&
|
|
236
|
+
(receipt.extent === undefined ||
|
|
237
|
+
(receipt.extent.length === 3 &&
|
|
238
|
+
receipt.extent.every((value) => Number.isFinite(value) && value > 0))) &&
|
|
239
|
+
Number.isInteger(receipt.sourceGeneration) &&
|
|
240
|
+
receipt.sourceGeneration >= 0 &&
|
|
241
|
+
Number.isInteger(receipt.projectionGeneration) &&
|
|
242
|
+
receipt.projectionGeneration >= 0 &&
|
|
243
|
+
Number.isInteger(receipt.deviceGeneration) &&
|
|
244
|
+
receipt.deviceGeneration >= 0 &&
|
|
245
|
+
receipt.brdfSignature === 'standard-pbr-ibl-v1' &&
|
|
246
|
+
((receipt.source === 'probe' && (receipt.state === 'active' || receipt.state === 'lkg')) ||
|
|
247
|
+
(receipt.source === 'skylight' && (receipt.state === 'active' || receipt.state === 'lkg')) ||
|
|
248
|
+
(receipt.source === 'neutral' && receipt.state === 'neutral'))
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function validFormat(receipt: SsrFormatReceipt | undefined): boolean {
|
|
253
|
+
if (
|
|
254
|
+
receipt?.profile !== SSR_FORMAT_PROFILE ||
|
|
255
|
+
receipt.verdict !== 'admitted' ||
|
|
256
|
+
receipt.evidence !== 'real' ||
|
|
257
|
+
!Number.isInteger(receipt.deviceGeneration) ||
|
|
258
|
+
receipt.deviceGeneration < 0
|
|
259
|
+
) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
if (
|
|
263
|
+
!SSR_FORMAT_STAGES.every((stage) =>
|
|
264
|
+
receipt.stages.some((entry) => entry.stage === stage && entry.verdict === 'admitted'),
|
|
265
|
+
)
|
|
266
|
+
) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
return validateR32FloatReceipt(receipt).ok;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function validTemporal(receipt: SsrTemporalReceipt | undefined): boolean {
|
|
273
|
+
return (
|
|
274
|
+
receipt?.successfulSubmit === true &&
|
|
275
|
+
Number.isInteger(receipt.generation) &&
|
|
276
|
+
receipt.generation >= 0
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function admitSsrM0(input: SsrAdmissionInput): SsrAdmissionResult {
|
|
281
|
+
if (!input.requested) {
|
|
282
|
+
return blocked(
|
|
283
|
+
input.identity,
|
|
284
|
+
failure('ssr-not-requested', 'consumer', 'request SSR before evaluating M0 admission'),
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
if (input.reflectionFallback === undefined) {
|
|
288
|
+
return blocked(
|
|
289
|
+
input.identity,
|
|
290
|
+
failure('ssr-reflection-fallback-unavailable', 'producer', 'use LKG, Skylight, or neutral'),
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
const fallbackIdentityFailure = receiptFailure(input, input.reflectionFallback, 'producer');
|
|
294
|
+
if (fallbackIdentityFailure !== undefined) return fallbackIdentityFailure;
|
|
295
|
+
if (!validFallback(input.reflectionFallback)) {
|
|
296
|
+
return blocked(
|
|
297
|
+
input.identity,
|
|
298
|
+
failure(
|
|
299
|
+
'ssr-reflection-fallback-unavailable',
|
|
300
|
+
'producer',
|
|
301
|
+
'inspect and rebuild the producer receipt',
|
|
302
|
+
),
|
|
303
|
+
input.reflectionFallback.projectionGeneration,
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
if (input.format === undefined) {
|
|
307
|
+
return blocked(
|
|
308
|
+
input.identity,
|
|
309
|
+
failure('ssr-format-unavailable', 'format', 'probe the exact format profile for this device'),
|
|
310
|
+
input.reflectionFallback.projectionGeneration,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
const formatIdentityFailure = receiptFailure(input, input.format, 'format');
|
|
314
|
+
if (formatIdentityFailure !== undefined) return formatIdentityFailure;
|
|
315
|
+
if (!validFormat(input.format)) {
|
|
316
|
+
return blocked(
|
|
317
|
+
input.identity,
|
|
318
|
+
failure('ssr-format-unavailable', 'format', 'complete the full r32float profile probe'),
|
|
319
|
+
input.reflectionFallback.projectionGeneration,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
if (input.temporal === undefined) {
|
|
323
|
+
return blocked(
|
|
324
|
+
input.identity,
|
|
325
|
+
failure(
|
|
326
|
+
'ssr-temporal-unavailable',
|
|
327
|
+
'temporal',
|
|
328
|
+
'submit the matching temporal producer receipt',
|
|
329
|
+
),
|
|
330
|
+
input.reflectionFallback.projectionGeneration,
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
const temporalIdentityFailure = receiptFailure(input, input.temporal, 'temporal');
|
|
334
|
+
if (temporalIdentityFailure !== undefined) return temporalIdentityFailure;
|
|
335
|
+
if (!validTemporal(input.temporal)) {
|
|
336
|
+
return blocked(
|
|
337
|
+
input.identity,
|
|
338
|
+
failure('ssr-temporal-unavailable', 'temporal', 'inspect and rebuild the temporal receipt'),
|
|
339
|
+
input.reflectionFallback.projectionGeneration,
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
if (
|
|
343
|
+
input.previousGeneration !== undefined &&
|
|
344
|
+
input.previousGeneration !== input.reflectionFallback.projectionGeneration
|
|
345
|
+
) {
|
|
346
|
+
return blocked(
|
|
347
|
+
input.identity,
|
|
348
|
+
failure(
|
|
349
|
+
'ssr-receipt-stale',
|
|
350
|
+
'consumer',
|
|
351
|
+
'discard stale completion and reinspect the owners',
|
|
352
|
+
{
|
|
353
|
+
generation: input.reflectionFallback.projectionGeneration,
|
|
354
|
+
},
|
|
355
|
+
),
|
|
356
|
+
input.reflectionFallback.projectionGeneration,
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
return Object.freeze({
|
|
360
|
+
status: 'admitted',
|
|
361
|
+
identity: input.identity,
|
|
362
|
+
generation: input.reflectionFallback.projectionGeneration,
|
|
363
|
+
work: ADMITTED_WORK,
|
|
364
|
+
budget: ADMITTED_BUDGET,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Joins the live owner projections at the renderer boundary. The only casts
|
|
370
|
+
* here add the host identity to receipts that otherwise remain canonical RHI
|
|
371
|
+
* or ReflectionProbe PODs; no producer fact is copied or renamed.
|
|
372
|
+
*/
|
|
373
|
+
export function projectSsrDependencies(input: {
|
|
374
|
+
readonly requested: boolean;
|
|
375
|
+
readonly identity: SsrAdmissionIdentity | undefined;
|
|
376
|
+
readonly reflectionFallback: ReflectionFallbackReceipt | undefined;
|
|
377
|
+
readonly format: RhiTextureFormatCapabilityReceipt | undefined;
|
|
378
|
+
readonly temporal: { readonly successfulSubmit: true; readonly generation: number } | undefined;
|
|
379
|
+
readonly previousGeneration?: number;
|
|
380
|
+
}): SsrDependenciesInspection {
|
|
381
|
+
const identity = input.identity;
|
|
382
|
+
const reflectionFallback =
|
|
383
|
+
identity === undefined || input.reflectionFallback?.identity === undefined
|
|
384
|
+
? undefined
|
|
385
|
+
: (input.reflectionFallback as SsrReflectionFallbackReceipt);
|
|
386
|
+
const format =
|
|
387
|
+
identity === undefined || input.format === undefined
|
|
388
|
+
? undefined
|
|
389
|
+
: ({ ...input.format, identity } satisfies SsrFormatReceipt);
|
|
390
|
+
const temporal =
|
|
391
|
+
identity === undefined || input.temporal === undefined
|
|
392
|
+
? undefined
|
|
393
|
+
: ({ identity, ...input.temporal } satisfies SsrTemporalReceipt);
|
|
394
|
+
const admission =
|
|
395
|
+
identity === undefined
|
|
396
|
+
? blocked(
|
|
397
|
+
undefined,
|
|
398
|
+
failure(
|
|
399
|
+
input.requested ? 'ssr-receipt-identity-mismatch' : 'ssr-not-requested',
|
|
400
|
+
'consumer',
|
|
401
|
+
input.requested
|
|
402
|
+
? 'bind the exact source, tree, lock, and build identity before admission'
|
|
403
|
+
: 'request SSR before evaluating M0 admission',
|
|
404
|
+
input.requested ? { identityField: 'sourceHead' } : {},
|
|
405
|
+
),
|
|
406
|
+
)
|
|
407
|
+
: admitSsrM0({
|
|
408
|
+
requested: input.requested,
|
|
409
|
+
identity,
|
|
410
|
+
...(reflectionFallback === undefined ? {} : { reflectionFallback }),
|
|
411
|
+
...(format === undefined ? {} : { format }),
|
|
412
|
+
...(temporal === undefined ? {} : { temporal }),
|
|
413
|
+
...(input.previousGeneration === undefined
|
|
414
|
+
? {}
|
|
415
|
+
: { previousGeneration: input.previousGeneration }),
|
|
416
|
+
});
|
|
417
|
+
return Object.freeze({
|
|
418
|
+
status: admission.status,
|
|
419
|
+
identity,
|
|
420
|
+
requested: input.requested,
|
|
421
|
+
reflectionFallback: input.reflectionFallback,
|
|
422
|
+
format,
|
|
423
|
+
temporal,
|
|
424
|
+
admission,
|
|
425
|
+
work: admission.work,
|
|
426
|
+
budget: admission.budget,
|
|
427
|
+
failure: admission.failure,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export function zeroSsrAdmissionWork(): SsrAdmissionWork {
|
|
432
|
+
return ZERO_WORK;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Projects the admission decision into the existing temporal reset seam.
|
|
437
|
+
* Admission never creates temporal history; only a changed committed
|
|
438
|
+
* producer generation can request a reset through the coordinator.
|
|
439
|
+
*/
|
|
440
|
+
export function resolveSsrAdmissionGeneration(
|
|
441
|
+
previousGeneration: number | undefined,
|
|
442
|
+
nextGeneration: number | undefined,
|
|
443
|
+
): { readonly changed: boolean; readonly generation: number | undefined } {
|
|
444
|
+
return {
|
|
445
|
+
changed:
|
|
446
|
+
previousGeneration !== undefined &&
|
|
447
|
+
nextGeneration !== undefined &&
|
|
448
|
+
previousGeneration !== nextGeneration,
|
|
449
|
+
generation: nextGeneration,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
2
|
+
|
|
3
|
+
/** Linear HDR RGB used by the M0 composition contract. */
|
|
4
|
+
export type SsrReflectionColor = readonly [number, number, number];
|
|
5
|
+
|
|
6
|
+
export interface SsrCompositionInput {
|
|
7
|
+
/** Screen-hit confidence. The parent SSR consumer supplies 0..1. */
|
|
8
|
+
readonly c: number;
|
|
9
|
+
/** The Standard BRDF specular lobe before SSR replacement. */
|
|
10
|
+
readonly baseSpecular: SsrReflectionColor;
|
|
11
|
+
/** The same-source BRDF-projected screen contribution. */
|
|
12
|
+
readonly screenSpecular: SsrReflectionColor;
|
|
13
|
+
/** The committed producer-owned environment contribution. */
|
|
14
|
+
readonly fallbackSpecular: SsrReflectionColor;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface SsrCompositionInputError {
|
|
18
|
+
readonly code: 'ssr-composition-input-invalid';
|
|
19
|
+
readonly expected: string;
|
|
20
|
+
readonly hint: string;
|
|
21
|
+
readonly detail: Readonly<{
|
|
22
|
+
readonly field: 'c' | 'baseSpecular' | 'screenSpecular' | 'fallbackSpecular';
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type SsrCompositionResult = Result<SsrReflectionColor, SsrCompositionInputError>;
|
|
27
|
+
|
|
28
|
+
function finiteColor(value: SsrReflectionColor): boolean {
|
|
29
|
+
return value.length === 3 && value.every(Number.isFinite);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function invalid(
|
|
33
|
+
field: SsrCompositionInputError['detail']['field'],
|
|
34
|
+
expected: string,
|
|
35
|
+
): SsrCompositionResult {
|
|
36
|
+
return err({
|
|
37
|
+
code: 'ssr-composition-input-invalid',
|
|
38
|
+
expected,
|
|
39
|
+
hint: 'preserve linear HDR and the bounded SSR confidence before composing',
|
|
40
|
+
detail: Object.freeze({ field }),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Apply the M0 reflection replacement contract without owning an SSR pass.
|
|
46
|
+
*
|
|
47
|
+
* `c=0` returns the base Standard specular lobe. `c=1` replaces only that
|
|
48
|
+
* lobe with the same-source screen contribution, subtracting the committed
|
|
49
|
+
* environment contribution once. Hi-Z traversal, history and graph wiring
|
|
50
|
+
* remain owned by the parent SSR feature.
|
|
51
|
+
*/
|
|
52
|
+
export function composeSsrReflection(input: SsrCompositionInput): SsrCompositionResult {
|
|
53
|
+
if (!Number.isFinite(input.c) || input.c < 0 || input.c > 1) {
|
|
54
|
+
return invalid('c', 'a finite confidence in the inclusive range 0..1');
|
|
55
|
+
}
|
|
56
|
+
for (const [field, value] of [
|
|
57
|
+
['baseSpecular', input.baseSpecular],
|
|
58
|
+
['screenSpecular', input.screenSpecular],
|
|
59
|
+
['fallbackSpecular', input.fallbackSpecular],
|
|
60
|
+
] as const) {
|
|
61
|
+
if (!finiteColor(value)) {
|
|
62
|
+
return invalid(field, 'three finite linear HDR RGB channels');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const c = input.c;
|
|
66
|
+
return ok(
|
|
67
|
+
Object.freeze([
|
|
68
|
+
input.baseSpecular[0] + c * (input.screenSpecular[0] - input.fallbackSpecular[0]),
|
|
69
|
+
input.baseSpecular[1] + c * (input.screenSpecular[1] - input.fallbackSpecular[1]),
|
|
70
|
+
input.baseSpecular[2] + c * (input.screenSpecular[2] - input.fallbackSpecular[2]),
|
|
71
|
+
]) as SsrReflectionColor,
|
|
72
|
+
);
|
|
73
|
+
}
|