@forgeax/engine-render 0.1.32 → 0.1.34
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 +1374 -142
- package/dist/assembly/analytic-fog-registration.d.ts +3 -0
- package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
- package/dist/assembly/backend-contract.d.ts +2 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
- package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
- package/dist/assembly/canvas-draw-guard.d.ts +3 -0
- package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
- package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
- package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
- package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
- package/dist/assembly/factory.d.ts +1 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/fxaa-registration.d.ts +4 -0
- package/dist/assembly/fxaa-registration.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +3 -3
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/lod-observation.d.ts +4 -0
- package/dist/assembly/lod-observation.d.ts.map +1 -0
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
- package/dist/assembly/material-shader-policy.d.ts +16 -2
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
- package/dist/assembly/motion-blur-registration.d.ts +3 -0
- package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/render-feature-post-processes.d.ts +6 -0
- package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
- package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-inspection.d.ts +11 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -1
- package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
- package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
- package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
- package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +2 -2
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/barrel-distortion.d.ts +47 -0
- package/dist/barrel-distortion.d.ts.map +1 -0
- package/dist/bloom-admission.d.ts +13 -0
- package/dist/bloom-admission.d.ts.map +1 -0
- package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
- package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
- package/dist/{chunk-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
- package/dist/chunk-HEB564WF.mjs.map +1 -0
- package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
- package/dist/chunk-MKDIT2EM.mjs.map +1 -0
- package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
- package/dist/{chunk-S665NJNF.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
- package/dist/chunk-ODZWR6JQ.mjs +4927 -0
- package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
- package/dist/{chunk-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
- package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
- package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
- package/dist/chunk-UI5SFODX.mjs.map +1 -0
- package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
- package/dist/chunk-UINHLCZA.mjs.map +1 -0
- package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
- package/dist/chunk-WEX45HKH.mjs.map +1 -0
- package/dist/cloud/density.d.ts +55 -0
- package/dist/cloud/density.d.ts.map +1 -0
- package/dist/cloud/extract.d.ts +25 -0
- package/dist/cloud/extract.d.ts.map +1 -0
- package/dist/cloud/feature.d.ts +57 -0
- package/dist/cloud/feature.d.ts.map +1 -0
- package/dist/cloud/frame-context.d.ts +8 -0
- package/dist/cloud/frame-context.d.ts.map +1 -0
- package/dist/cloud/inspection.d.ts +59 -0
- package/dist/cloud/inspection.d.ts.map +1 -0
- package/dist/cloud/optics.d.ts +56 -0
- package/dist/cloud/optics.d.ts.map +1 -0
- package/dist/cloud/parameters.d.ts +73 -0
- package/dist/cloud/parameters.d.ts.map +1 -0
- package/dist/cloud/resources.d.ts +60 -0
- package/dist/cloud/resources.d.ts.map +1 -0
- package/dist/cloud/shadow.d.ts +42 -0
- package/dist/cloud/shadow.d.ts.map +1 -0
- package/dist/cloud/temporal.d.ts +74 -0
- package/dist/cloud/temporal.d.ts.map +1 -0
- package/dist/components/atmosphere.d.ts +2 -0
- package/dist/components/atmosphere.d.ts.map +1 -1
- package/dist/components/barrel-distortion.d.ts +13 -0
- package/dist/components/barrel-distortion.d.ts.map +1 -0
- package/dist/components/camera.d.ts +20 -4
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/cloud-layer.d.ts +29 -0
- package/dist/components/cloud-layer.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +20 -6
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/components/mesh-filter.d.ts +6 -5
- package/dist/components/mesh-filter.d.ts.map +1 -1
- package/dist/components/motion-blur.d.ts +1 -0
- package/dist/components/motion-blur.d.ts.map +1 -1
- package/dist/construct-renderer.d.ts +1 -1
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +9751 -3528
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +6 -0
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/dynamic-geometry.d.ts +5 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/environment/analytic-fog.d.ts +6 -0
- package/dist/environment/analytic-fog.d.ts.map +1 -0
- package/dist/errors/cloud.d.ts +59 -0
- package/dist/errors/cloud.d.ts.map +1 -0
- package/dist/errors/render.d.ts +23 -5
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/examples/single-layer-medium-surface.d.ts +47 -0
- package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +12 -1
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/environment.d.ts +2 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/features/barrel-distortion.d.ts +29 -0
- package/dist/features/barrel-distortion.d.ts.map +1 -0
- package/dist/features/error-reporting.d.ts +17 -0
- package/dist/features/error-reporting.d.ts.map +1 -0
- package/dist/features/host.d.ts +15 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
- package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
- package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
- package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
- package/dist/features/plan.d.ts +15 -4
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +9 -5
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/render-graph-compute.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +5 -0
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +1 -0
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/targets.d.ts +2 -0
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +44 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +15 -7
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-dirty-ranges.d.ts +11 -0
- package/dist/gpu-dirty-ranges.d.ts.map +1 -0
- package/dist/gpu-driven/batch-topology.d.ts +17 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts +6 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts +7 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster-material.d.ts +178 -0
- package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +50 -4
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/resource-allocation.d.ts +31 -0
- package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
- package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
- package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +35 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +11 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +2 -2
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +10 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +31 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +258 -8
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +178 -3
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instance-buffer-cache.d.ts +4 -4
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +49 -94
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +7 -7
- package/dist/pbr-pipeline.d.ts +19 -1
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
- package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
- package/dist/pipeline/standard-output/types.d.ts +4 -2
- package/dist/pipeline/standard-output/types.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +28 -19
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +2 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/record/barrel-distortion-frame.d.ts +15 -0
- package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
- package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
- package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
- package/dist/record/fold-buckets.d.ts +95 -0
- package/dist/record/fold-buckets.d.ts.map +1 -0
- package/dist/record/fold-instance-buffer.d.ts +6 -0
- package/dist/record/fold-instance-buffer.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +1 -0
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +40 -3
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +14 -62
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-draw-receipts.d.ts +11 -0
- package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +8 -0
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +21 -5
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -1
- 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 +13 -2
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +6 -5
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/motion-blur-receipt.d.ts +11 -0
- package/dist/record/motion-blur-receipt.d.ts.map +1 -0
- package/dist/record/probe-blend-buffer.d.ts +16 -0
- package/dist/record/probe-blend-buffer.d.ts.map +1 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +34 -31
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -0
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +6 -4
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +22 -2
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +11 -3
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/record/volume-params.d.ts +9 -0
- package/dist/record/volume-params.d.ts.map +1 -0
- package/dist/recovery/render-system-candidate.d.ts +10 -0
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +66 -8
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +106 -3
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +3 -2
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +24 -10
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-presentation.d.ts +23 -0
- package/dist/render-system-presentation.d.ts.map +1 -0
- package/dist/render-system-producer-roots.d.ts +10 -0
- package/dist/render-system-producer-roots.d.ts.map +1 -0
- package/dist/render-system-residency.d.ts +12 -0
- package/dist/render-system-residency.d.ts.map +1 -0
- package/dist/render-system.d.ts +26 -15
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/probe-blend.d.ts +27 -0
- package/dist/scene/probe-blend.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +14 -5
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +9 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/surface/dynamic-input.d.ts +133 -0
- package/dist/surface/dynamic-input.d.ts.map +1 -0
- package/dist/surface/gpu-driven.d.ts +41 -0
- package/dist/surface/gpu-driven.d.ts.map +1 -0
- package/dist/surface/submission-observation.d.ts +136 -0
- package/dist/surface/submission-observation.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +7 -0
- package/dist/temporal/frame.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts +13 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- package/dist/temporal/inspection.d.ts.map +1 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
- package/dist/temporal/view.d.ts +6 -1
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/transmission/single-layer-medium.d.ts +89 -0
- package/dist/transmission/single-layer-medium.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +24 -9
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +9 -5
- package/dist/volume/component.d.ts.map +1 -1
- package/dist/volume/extract.d.ts +1 -1
- package/dist/volume/extract.d.ts.map +1 -1
- package/dist/volume/inspection.d.ts +2 -0
- package/dist/volume/inspection.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +4 -1
- package/dist/volume/passes.d.ts.map +1 -1
- package/dist/volume/resources.d.ts.map +1 -1
- package/dist/volume/temporal.d.ts +3 -1
- package/dist/volume/temporal.d.ts.map +1 -1
- package/package.json +22 -21
- package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
- package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
- package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
- package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
- package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
- package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
- package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
- package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
- package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
- package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
- package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
- package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
- package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
- package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
- package/src/__tests__/environment-selection.unit.test.ts +12 -0
- package/src/__tests__/factory-contract.integration.test.ts +626 -113
- package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
- package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
- package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
- package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +2 -1
- package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
- package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +7 -6
- package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
- package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
- package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
- package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
- package/src/__tests__/gpu-scene.unit.test.ts +210 -9
- package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
- package/src/__tests__/instances-culling.integration.test.ts +10 -36
- package/src/__tests__/instances-store.unit.test.ts +105 -238
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
- package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
- package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
- package/src/__tests__/motion-blur-compute.dawn.test.ts +589 -0
- package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
- package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
- package/src/__tests__/probe-bindings.unit.test.ts +582 -1
- package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
- package/src/__tests__/public-surface.test-d.ts +8 -0
- package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +9 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
- package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
- package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
- package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
- package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
- package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +37 -6
- package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
- package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
- package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +33 -11
- package/src/__tests__/resource-allocation.unit.test.ts +123 -0
- package/src/__tests__/shader-manifest-fixture.ts +4 -4
- package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
- package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +17 -0
- package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
- package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
- package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
- package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
- package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
- package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
- package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
- package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
- package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
- package/src/__tests__/temporal-performance.integration.test.ts +3 -3
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
- package/src/__tests__/temporal-view.unit.test.ts +2 -1
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
- package/src/__tests__/visibility-instances.integration.test.ts +7 -19
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
- package/src/__tests__/volume-optics-oracle.unit.test.ts +7 -3
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
- package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
- package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
- package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +558 -68
- package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
- package/src/assembly/analytic-fog-registration.ts +14 -0
- package/src/assembly/backend-contract.ts +30 -0
- package/src/assembly/barrel-distortion-inspection.ts +22 -0
- package/src/assembly/canvas-draw-guard.ts +11 -0
- package/src/assembly/cloud-shadow-entry.ts +22 -0
- package/src/assembly/dynamic-geometry-host.ts +65 -37
- package/src/assembly/dynamic-geometry-runtime.ts +7 -1
- package/src/assembly/factory.ts +2 -30
- package/src/assembly/fxaa-registration.ts +17 -0
- package/src/assembly/host-contract.ts +3 -3
- package/src/assembly/lod-observation.ts +12 -0
- package/src/assembly/material/assembly.ts +25 -13
- package/src/assembly/material/pipeline-helpers.ts +53 -12
- package/src/assembly/material-shader-policy.ts +55 -0
- package/src/assembly/material-shader-prewarm.ts +21 -10
- package/src/assembly/motion-blur-registration.ts +17 -0
- package/src/assembly/recovery/device-loss-fanout.ts +13 -0
- package/src/assembly/recovery/renderer-recover.ts +41 -18
- package/src/assembly/render-feature-post-processes.ts +54 -0
- package/src/assembly/renderer-facade.ts +6 -1
- package/src/assembly/renderer-feature-inspection.ts +8 -2
- package/src/assembly/renderer-frame-transaction.ts +23 -0
- package/src/assembly/renderer-inspection.ts +28 -0
- package/src/assembly/skin-palette-owner.ts +1 -1
- package/src/assembly/temporal-post-process-prewarm.ts +40 -0
- package/src/assembly/webgpu-pbr-ready.ts +9 -1
- package/src/assembly/webgpu-ready-contract.ts +8 -3
- package/src/assembly/webgpu-ready-per-pass.ts +104 -0
- package/src/assembly/webgpu-ready.ts +296 -306
- package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
- package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
- package/src/assembly/webgpu-renderer.ts +228 -281
- package/src/assembly/webgpu-vertex-layouts.ts +1 -1
- package/src/barrel-distortion.ts +247 -0
- package/src/bloom-admission.ts +21 -0
- package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
- package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
- package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
- package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
- package/src/cloud/density.ts +600 -0
- package/src/cloud/extract.ts +110 -0
- package/src/cloud/feature.ts +1810 -0
- package/src/cloud/frame-context.ts +42 -0
- package/src/cloud/inspection.ts +130 -0
- package/src/cloud/optics.ts +285 -0
- package/src/cloud/parameters.ts +255 -0
- package/src/cloud/resources.ts +122 -0
- package/src/cloud/shadow.ts +167 -0
- package/src/cloud/temporal.ts +226 -0
- package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
- package/src/components/atmosphere.ts +4 -0
- package/src/components/barrel-distortion.ts +46 -0
- package/src/components/camera.ts +66 -10
- package/src/components/cloud-layer.ts +47 -0
- package/src/components/index.ts +2 -0
- package/src/components/instances.ts +18 -45
- package/src/components/mesh-filter.ts +11 -9
- package/src/components/motion-blur.ts +1 -0
- package/src/components/sprite-instances.ts +1 -1
- package/src/construct-renderer.ts +1 -1
- package/src/device/gpu-residency.ts +56 -12
- package/src/dynamic-geometry.ts +12 -1
- package/src/environment/analytic-fog.ts +44 -0
- package/src/environment/background.ts +2 -2
- package/src/errors/cloud.ts +103 -0
- package/src/errors/render.ts +58 -8
- package/src/examples/single-layer-medium-surface.ts +59 -0
- package/src/extract/camera.ts +35 -8
- package/src/extract/contracts.ts +12 -0
- package/src/extract/environment.ts +4 -0
- package/src/features/barrel-distortion.ts +172 -0
- package/src/features/error-reporting.ts +98 -0
- package/src/features/host.ts +138 -24
- package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
- package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
- package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
- package/src/features/motion-blur/motion-blur-params.ts +70 -2
- package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
- package/src/features/plan.ts +33 -8
- package/src/features/prepared-gpu-work.ts +86 -35
- package/src/features/render-graph-compute.ts +13 -5
- package/src/features/render-graph-contribution.ts +11 -0
- package/src/features/render-graph-raster.ts +45 -3
- package/src/features/targets.ts +66 -0
- package/src/features/types.ts +47 -0
- package/src/fullscreen-post-process-pass.ts +41 -9
- package/src/gpu-dirty-ranges.ts +48 -0
- package/src/gpu-driven/batch-topology.ts +53 -0
- package/src/gpu-driven/material-artifacts.ts +35 -32
- package/src/gpu-driven/prepared-draw.ts +27 -14
- package/src/gpu-driven/production-raster-material.ts +1894 -0
- package/src/gpu-driven/production-raster.ts +904 -787
- package/src/gpu-driven/resource-allocation.ts +142 -0
- package/src/gpu-driven/shadow-ownership.ts +71 -0
- package/src/gpu-driven/view-gpu.ts +181 -10
- package/src/gpu-scene.ts +259 -101
- package/src/hdrp-buffers.ts +4 -3
- package/src/ibl/skylight-bind-group.ts +49 -7
- package/src/index.ts +228 -9
- package/src/inspection-types.ts +222 -2
- package/src/instance-buffer-cache.ts +4 -4
- package/src/instances.ts +151 -492
- package/src/pbr-pipeline.ts +219 -13
- package/src/pipeline/single-layer-medium-passes.ts +267 -0
- package/src/pipeline/standard-forward-lane.ts +313 -57
- package/src/pipeline/standard-output/graph.ts +8 -2
- package/src/pipeline/standard-output/types.ts +12 -1
- package/src/pipeline/standard-pipeline.ts +291 -18
- package/src/pipeline/standard-post.ts +397 -102
- package/src/pipeline-builder.ts +1 -1
- package/src/pipeline-spec.ts +5 -5
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
- package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
- package/src/prepare/prepared-graphics-resolver.ts +2 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
- package/src/record/__tests__/temporal-payload.unit.test.ts +3 -2
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
- package/src/record/barrel-distortion-frame.ts +110 -0
- package/src/record/dynamic-geometry-consumption.ts +39 -9
- package/src/record/fold-buckets.ts +852 -0
- package/src/record/fold-instance-buffer.ts +51 -0
- package/src/record/frame-lighting.ts +36 -2
- package/src/record/frame-snapshot.ts +44 -4
- package/src/record/frame-targets.ts +10 -6
- package/src/record/frame.ts +373 -1099
- package/src/record/gpu-draw-receipts.ts +38 -0
- package/src/record/gpu-timing.ts +48 -5
- package/src/record/main-pass-geometry.ts +281 -83
- package/src/record/main-pass-material.ts +66 -4
- package/src/record/main-pass-sprite-draws.ts +13 -66
- package/src/record/main-pass.ts +156 -20
- package/src/record/mesh-ssbo.ts +43 -6
- package/src/record/motion-blur-receipt.ts +91 -0
- package/src/record/probe-blend-buffer.ts +180 -0
- package/src/record/recovery-pipeline.ts +35 -3
- package/src/record/render-context.ts +51 -31
- package/src/record/shadow-pass.ts +36 -2
- package/src/record/skybox-post-pass.ts +150 -200
- package/src/record/typed-frame-graph.ts +824 -44
- package/src/record/view-ubo.ts +26 -3
- package/src/record/volume-params.ts +225 -0
- package/src/recovery/render-system-candidate.ts +257 -52
- package/src/reflection/record-owner.ts +7 -3
- package/src/render-contract.ts +71 -8
- package/src/render-graph-primitives.ts +7 -1
- package/src/render-pipeline.ts +136 -1
- package/src/render-system-extract-tail.ts +72 -60
- package/src/render-system-extract.ts +117 -87
- package/src/render-system-presentation.ts +56 -0
- package/src/render-system-producer-roots.ts +96 -0
- package/src/render-system-residency.ts +159 -0
- package/src/render-system.ts +601 -482
- package/src/scene/probe-blend.ts +96 -4
- package/src/scene/render-scene.ts +431 -281
- package/src/ssao-buffers.ts +95 -2
- package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
- package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
- package/src/surface/dynamic-input.ts +658 -0
- package/src/surface/gpu-driven.ts +147 -0
- package/src/surface/submission-observation.ts +517 -0
- package/src/systems/skin-palette-allocator.ts +4 -1
- package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
- package/src/temporal/frame-coordinator.ts +8 -1
- package/src/temporal/frame.ts +20 -0
- package/src/temporal/gpu.ts +101 -17
- package/src/temporal/inspection.ts +7 -1
- package/src/temporal/standard-scene-data.ts +5 -0
- package/src/temporal/target-coverage-attachment.ts +4 -0
- package/src/temporal/view.ts +13 -2
- package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
- package/src/transmission/single-layer-medium.ts +322 -0
- package/src/typed-render-graph-primitives.ts +191 -50
- package/src/volume/component.ts +10 -10
- package/src/volume/extract.ts +11 -5
- package/src/volume/inspection.ts +3 -0
- package/src/volume/passes.ts +95 -8
- package/src/volume/resources.ts +2 -1
- package/src/volume/temporal.ts +11 -0
- package/dist/chunk-4NNZQCL3.mjs.map +0 -1
- package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
- package/dist/chunk-DRR7D3KX.mjs.map +0 -1
- package/dist/chunk-GWCEMDVR.mjs.map +0 -1
- package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
- package/dist/chunk-JRIPCMYC.mjs.map +0 -1
- package/dist/chunk-LULCA3OF.mjs +0 -1713
- package/dist/chunk-LULCA3OF.mjs.map +0 -1
- package/dist/chunk-PA5DRJNI.mjs.map +0 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { createTemporalFrameTransaction } from '../frame';
|
|
3
|
+
|
|
4
|
+
function frame(frameId: number, resetReason?: 'camera-cut') {
|
|
5
|
+
return {
|
|
6
|
+
frameId,
|
|
7
|
+
currentViewProjection: new Float32Array(16),
|
|
8
|
+
jitter: [0, 0] as [number, number],
|
|
9
|
+
viewport: { width: 64, height: 64 },
|
|
10
|
+
cameraPosition: [frameId, 0, 0] as [number, number, number],
|
|
11
|
+
...(resetReason === undefined ? {} : { resetReason }),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
describe('renderer temporal candidate lifecycle', () => {
|
|
16
|
+
it('projects a rejected submit while retaining the accepted baseline', () => {
|
|
17
|
+
const transaction = createTemporalFrameTransaction({ deviceEpoch: 4 });
|
|
18
|
+
transaction.stage(frame(1));
|
|
19
|
+
expect(transaction.commit({ accepted: true }).ok).toBe(true);
|
|
20
|
+
const baseline = transaction.snapshot();
|
|
21
|
+
|
|
22
|
+
transaction.stage(frame(2));
|
|
23
|
+
expect(transaction.commit({ accepted: false, reason: 'queue-submit-failed' }).ok).toBe(false);
|
|
24
|
+
expect(transaction.snapshot()).toEqual(baseline);
|
|
25
|
+
expect(transaction.inspect()).toEqual({
|
|
26
|
+
accepted: true,
|
|
27
|
+
staged: false,
|
|
28
|
+
lastFailure: 'queue-submit-failed',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
transaction.stage(frame(3));
|
|
32
|
+
expect(transaction.commit({ accepted: true }).ok).toBe(true);
|
|
33
|
+
expect(transaction.inspect()).toEqual({ accepted: true, staged: false });
|
|
34
|
+
expect(transaction.snapshot().frameId).toBe(3);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
2
|
+
import { motionBlurTemporalDemand } from '../features/motion-blur/motion-blur-params';
|
|
2
3
|
import type { CameraSnapshot } from '../render-contract';
|
|
3
4
|
import { classifySceneDataCoverage, type SceneDataContributor } from './coverage';
|
|
4
5
|
import { type TaaHistoryAttempt, TaaHistoryStore } from './taa-history-store';
|
|
@@ -301,7 +302,13 @@ export class TemporalFrameCoordinator<T = unknown> {
|
|
|
301
302
|
): TemporalView | undefined {
|
|
302
303
|
const demanded =
|
|
303
304
|
camera.antialias === 'taa' ||
|
|
304
|
-
(camera.motionBlur
|
|
305
|
+
(camera.motionBlur !== undefined &&
|
|
306
|
+
motionBlurTemporalDemand({
|
|
307
|
+
shutterAngle: camera.motionBlur.shutterAngle,
|
|
308
|
+
maxRadiusPixels: camera.motionBlur.maxRadiusPixels,
|
|
309
|
+
sampleCount: camera.motionBlur.sampleCount,
|
|
310
|
+
targetFps: camera.motionBlur.targetFps ?? 60,
|
|
311
|
+
}));
|
|
305
312
|
if (!demanded) return undefined;
|
|
306
313
|
return projectTemporalView({
|
|
307
314
|
camera,
|
package/src/temporal/frame.ts
CHANGED
|
@@ -40,10 +40,18 @@ export interface TemporalSubmitResult {
|
|
|
40
40
|
readonly resetReason?: Exclude<TemporalResetReason, 'none' | 'queue-submit-failed'>;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/** Detached candidate/lifecycle facts consumed by Renderer inspection. */
|
|
44
|
+
export interface TemporalFrameTransactionInspection {
|
|
45
|
+
readonly accepted: boolean;
|
|
46
|
+
readonly staged: boolean;
|
|
47
|
+
readonly lastFailure?: 'queue-submit-failed';
|
|
48
|
+
}
|
|
49
|
+
|
|
43
50
|
export interface TemporalFrameTransaction {
|
|
44
51
|
stage(input: TemporalFrameInput): void;
|
|
45
52
|
commit(submit: TemporalSubmitResult): Result<TemporalFrame, TemporalFrameSubmitError>;
|
|
46
53
|
snapshot(): TemporalFrame;
|
|
54
|
+
inspect(): TemporalFrameTransactionInspection;
|
|
47
55
|
/** Drop accepted/staged history after a producer or device generation cut. */
|
|
48
56
|
reset(reason?: Extract<TemporalResetReason, 'signature-change' | 'device-recovery'>): void;
|
|
49
57
|
}
|
|
@@ -85,6 +93,7 @@ export function createTemporalFrameTransaction(options: {
|
|
|
85
93
|
let staged: TemporalFrameInput | undefined;
|
|
86
94
|
let historyEpoch = 0;
|
|
87
95
|
let pendingResetReason: Exclude<TemporalResetReason, 'none' | 'queue-submit-failed'> | undefined;
|
|
96
|
+
let lastFailure: TemporalFrameTransactionInspection['lastFailure'];
|
|
88
97
|
|
|
89
98
|
return {
|
|
90
99
|
stage(input) {
|
|
@@ -93,9 +102,11 @@ export function createTemporalFrameTransaction(options: {
|
|
|
93
102
|
commit(submit) {
|
|
94
103
|
if (!submit.accepted) {
|
|
95
104
|
staged = undefined;
|
|
105
|
+
lastFailure = submit.reason ?? 'queue-submit-failed';
|
|
96
106
|
return err(new TemporalFrameSubmitError(submit.reason ?? 'queue-submit-failed'));
|
|
97
107
|
}
|
|
98
108
|
if (staged === undefined) {
|
|
109
|
+
lastFailure = 'queue-submit-failed';
|
|
99
110
|
return err(new TemporalFrameSubmitError('queue-submit-failed'));
|
|
100
111
|
}
|
|
101
112
|
|
|
@@ -121,6 +132,7 @@ export function createTemporalFrameTransaction(options: {
|
|
|
121
132
|
accepted = next;
|
|
122
133
|
staged = undefined;
|
|
123
134
|
pendingResetReason = undefined;
|
|
135
|
+
lastFailure = undefined;
|
|
124
136
|
return ok(copyFrame(next));
|
|
125
137
|
},
|
|
126
138
|
snapshot() {
|
|
@@ -128,6 +140,13 @@ export function createTemporalFrameTransaction(options: {
|
|
|
128
140
|
throw new Error('TemporalFrame snapshot is unavailable before commit');
|
|
129
141
|
return copyFrame(accepted);
|
|
130
142
|
},
|
|
143
|
+
inspect() {
|
|
144
|
+
return {
|
|
145
|
+
accepted: accepted !== undefined,
|
|
146
|
+
staged: staged !== undefined,
|
|
147
|
+
...(lastFailure === undefined ? {} : { lastFailure }),
|
|
148
|
+
};
|
|
149
|
+
},
|
|
131
150
|
reset(reason = 'signature-change') {
|
|
132
151
|
accepted = undefined;
|
|
133
152
|
staged = undefined;
|
|
@@ -136,6 +155,7 @@ export function createTemporalFrameTransaction(options: {
|
|
|
136
155
|
// committed frame prevents stale motion vectors from crossing the
|
|
137
156
|
// producer/device boundary.
|
|
138
157
|
pendingResetReason = reason;
|
|
158
|
+
lastFailure = undefined;
|
|
139
159
|
},
|
|
140
160
|
};
|
|
141
161
|
}
|
package/src/temporal/gpu.ts
CHANGED
|
@@ -23,6 +23,13 @@ export const TEMPORAL_HISTORY_FORMATS = Object.freeze({
|
|
|
23
23
|
stability: 'r8unorm',
|
|
24
24
|
} as const);
|
|
25
25
|
|
|
26
|
+
/** Cloud transport history shares the renderer temporal owner and ping-pong fence. */
|
|
27
|
+
export const CLOUD_HISTORY_FORMATS = Object.freeze({
|
|
28
|
+
radiance: 'rgba16float',
|
|
29
|
+
transmittance: 'rgba16float',
|
|
30
|
+
depth: 'rgba16float',
|
|
31
|
+
} as const);
|
|
32
|
+
|
|
26
33
|
interface TemporalSurface {
|
|
27
34
|
readonly texture: Texture;
|
|
28
35
|
readonly view: TextureView;
|
|
@@ -40,6 +47,12 @@ export interface TemporalGpuState {
|
|
|
40
47
|
readonly color: [TemporalSurface, TemporalSurface];
|
|
41
48
|
readonly temporal: [TemporalSurface, TemporalSurface];
|
|
42
49
|
readonly stability: [TemporalSurface, TemporalSurface];
|
|
50
|
+
/** Whether this candidate owns the optional cloud transport history MRT. */
|
|
51
|
+
readonly cloudHistoryEnabled: boolean;
|
|
52
|
+
/** Previous/current cloud radiance, transmittance and representative depth. */
|
|
53
|
+
readonly cloudRadiance: [TemporalSurface, TemporalSurface] | undefined;
|
|
54
|
+
readonly cloudTransmittance: [TemporalSurface, TemporalSurface] | undefined;
|
|
55
|
+
readonly cloudDepth: [TemporalSurface, TemporalSurface] | undefined;
|
|
43
56
|
bindGroupLayout: BindGroupLayout | undefined;
|
|
44
57
|
sampler: Sampler | undefined;
|
|
45
58
|
temporalSampler: Sampler | undefined;
|
|
@@ -81,13 +94,22 @@ function createSurface(
|
|
|
81
94
|
return { texture: texture.value, view: view.value };
|
|
82
95
|
}
|
|
83
96
|
|
|
97
|
+
function cloudHistoryExtent(width: number, height: number): { width: number; height: number } {
|
|
98
|
+
return {
|
|
99
|
+
width: Math.max(1, Math.ceil(width / 2)),
|
|
100
|
+
height: Math.max(1, Math.ceil(height / 2)),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
84
104
|
function createState(
|
|
85
105
|
device: RhiDevice,
|
|
86
106
|
scope: DeviceScope,
|
|
87
107
|
width: number,
|
|
88
108
|
height: number,
|
|
109
|
+
cloudHistoryEnabled: boolean,
|
|
89
110
|
): TemporalGpuState {
|
|
90
111
|
const childScope = scope.createChild(`${scope.owner}:temporal`);
|
|
112
|
+
const cloudExtent = cloudHistoryExtent(width, height);
|
|
91
113
|
try {
|
|
92
114
|
return {
|
|
93
115
|
device,
|
|
@@ -138,6 +160,65 @@ function createState(
|
|
|
138
160
|
TEMPORAL_HISTORY_FORMATS.stability,
|
|
139
161
|
),
|
|
140
162
|
],
|
|
163
|
+
cloudHistoryEnabled,
|
|
164
|
+
cloudRadiance: cloudHistoryEnabled
|
|
165
|
+
? [
|
|
166
|
+
createSurface(
|
|
167
|
+
device,
|
|
168
|
+
childScope,
|
|
169
|
+
'cloud-history-radiance-a',
|
|
170
|
+
cloudExtent.width,
|
|
171
|
+
cloudExtent.height,
|
|
172
|
+
),
|
|
173
|
+
createSurface(
|
|
174
|
+
device,
|
|
175
|
+
childScope,
|
|
176
|
+
'cloud-history-radiance-b',
|
|
177
|
+
cloudExtent.width,
|
|
178
|
+
cloudExtent.height,
|
|
179
|
+
),
|
|
180
|
+
]
|
|
181
|
+
: undefined,
|
|
182
|
+
cloudTransmittance: cloudHistoryEnabled
|
|
183
|
+
? [
|
|
184
|
+
createSurface(
|
|
185
|
+
device,
|
|
186
|
+
childScope,
|
|
187
|
+
'cloud-history-transmittance-a',
|
|
188
|
+
cloudExtent.width,
|
|
189
|
+
cloudExtent.height,
|
|
190
|
+
CLOUD_HISTORY_FORMATS.transmittance,
|
|
191
|
+
),
|
|
192
|
+
createSurface(
|
|
193
|
+
device,
|
|
194
|
+
childScope,
|
|
195
|
+
'cloud-history-transmittance-b',
|
|
196
|
+
cloudExtent.width,
|
|
197
|
+
cloudExtent.height,
|
|
198
|
+
CLOUD_HISTORY_FORMATS.transmittance,
|
|
199
|
+
),
|
|
200
|
+
]
|
|
201
|
+
: undefined,
|
|
202
|
+
cloudDepth: cloudHistoryEnabled
|
|
203
|
+
? [
|
|
204
|
+
createSurface(
|
|
205
|
+
device,
|
|
206
|
+
childScope,
|
|
207
|
+
'cloud-history-depth-a',
|
|
208
|
+
cloudExtent.width,
|
|
209
|
+
cloudExtent.height,
|
|
210
|
+
CLOUD_HISTORY_FORMATS.depth,
|
|
211
|
+
),
|
|
212
|
+
createSurface(
|
|
213
|
+
device,
|
|
214
|
+
childScope,
|
|
215
|
+
'cloud-history-depth-b',
|
|
216
|
+
cloudExtent.width,
|
|
217
|
+
cloudExtent.height,
|
|
218
|
+
CLOUD_HISTORY_FORMATS.depth,
|
|
219
|
+
),
|
|
220
|
+
]
|
|
221
|
+
: undefined,
|
|
141
222
|
bindGroupLayout: undefined,
|
|
142
223
|
sampler: undefined,
|
|
143
224
|
temporalSampler: undefined,
|
|
@@ -180,26 +261,29 @@ export function getTemporalGpuState(
|
|
|
180
261
|
scope: DeviceScope,
|
|
181
262
|
width: number,
|
|
182
263
|
height: number,
|
|
264
|
+
cloudHistoryRequested = false,
|
|
183
265
|
): TemporalGpuState {
|
|
266
|
+
// Graph preparation publishes this demand before any imported target is
|
|
267
|
+
// resolved. That makes the first TAA and cloud pass share one candidate,
|
|
268
|
+
// while a plain TAA frame allocates only its six TAA surfaces.
|
|
269
|
+
const wantsCloudHistory =
|
|
270
|
+
cloudHistoryRequested ||
|
|
271
|
+
frameState.pendingCloudHistoryActive === true ||
|
|
272
|
+
frameState.cloudHistoryActive === true;
|
|
273
|
+
const matches = (state: TemporalGpuState | undefined): state is TemporalGpuState =>
|
|
274
|
+
state !== undefined &&
|
|
275
|
+
state.scope === scope &&
|
|
276
|
+
state.width === width &&
|
|
277
|
+
state.height === height &&
|
|
278
|
+
// Cloud history is a demand-shaped part of the temporal allocation. Keep
|
|
279
|
+
// the two shapes distinct so turning CloudLayer off retires its six HDR
|
|
280
|
+
// surfaces instead of retaining them on an otherwise TAA-only frame.
|
|
281
|
+
state.cloudHistoryEnabled === wantsCloudHistory;
|
|
184
282
|
const staged = frameState.temporalGpuState;
|
|
185
|
-
if (
|
|
186
|
-
staged !== undefined &&
|
|
187
|
-
staged.scope === scope &&
|
|
188
|
-
staged.width === width &&
|
|
189
|
-
staged.height === height
|
|
190
|
-
) {
|
|
191
|
-
return staged;
|
|
192
|
-
}
|
|
283
|
+
if (matches(staged)) return staged;
|
|
193
284
|
const existing = frameState.activeTemporalGpuState;
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
existing.scope === scope &&
|
|
197
|
-
existing.width === width &&
|
|
198
|
-
existing.height === height
|
|
199
|
-
) {
|
|
200
|
-
return existing;
|
|
201
|
-
}
|
|
202
|
-
const next = createState(device, scope, width, height);
|
|
285
|
+
if (matches(existing)) return existing;
|
|
286
|
+
const next = createState(device, scope, width, height, wantsCloudHistory);
|
|
203
287
|
frameState.temporalGpuState = next;
|
|
204
288
|
return next;
|
|
205
289
|
}
|
|
@@ -29,7 +29,13 @@ export interface TemporalInspection {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
function gpuBytes(state: TemporalGpuState | undefined): number {
|
|
32
|
-
|
|
32
|
+
if (state === undefined) return 0;
|
|
33
|
+
const taaBytes = createTemporalCoverage(state.width, state.height).bytes;
|
|
34
|
+
// The cloud owner adds six rgba16float surfaces (8 bytes per pixel) only
|
|
35
|
+
// when the candidate was admitted with cloud history demand. This is derived
|
|
36
|
+
// from the live state shape rather than reported as a fixed cloud estimate.
|
|
37
|
+
const cloudBytes = state.cloudHistoryEnabled ? state.width * state.height * 6 * 8 : 0;
|
|
38
|
+
return taaBytes + cloudBytes;
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
function gpuResources(state: TemporalGpuState | undefined): number {
|
|
@@ -156,6 +156,11 @@ export function addStandardSceneDataPass(
|
|
|
156
156
|
color: target,
|
|
157
157
|
depth,
|
|
158
158
|
selector: { LightMode: ['Deferred', 'Forward'] },
|
|
159
|
+
// The temporal producer runs before the Surface raw-depth/nearest-layer
|
|
160
|
+
// pair. Keep it on the ordinary opaque Standard lane rather than asking
|
|
161
|
+
// a medium material to assemble a bind group from resources that this
|
|
162
|
+
// pass cannot own yet.
|
|
163
|
+
recordMode: 'opaque',
|
|
159
164
|
passKind: 'temporal',
|
|
160
165
|
// The temporal producer re-rasterizes the current scene after the main
|
|
161
166
|
// color pass has populated depth. Its output is a semantic motion target;
|
|
@@ -64,6 +64,10 @@ export function addTargetCoveragePass(
|
|
|
64
64
|
colorTargets: [target.coverage],
|
|
65
65
|
depth: target.depth,
|
|
66
66
|
selector: { LightMode: ['Deferred', 'Forward'] },
|
|
67
|
+
// Coverage is a generic Standard raster producer. Surface medium pixels
|
|
68
|
+
// are owned by the later paired nearest/color passes and have no raw-depth
|
|
69
|
+
// input at this point, so keep this attachment on the opaque lane.
|
|
70
|
+
recordMode: 'opaque',
|
|
67
71
|
passKind: 'temporal',
|
|
68
72
|
clearColor: [0, 0, 0, 0],
|
|
69
73
|
depthLoadOp: 'clear',
|
package/src/temporal/view.ts
CHANGED
|
@@ -21,6 +21,7 @@ export type TemporalResetReason =
|
|
|
21
21
|
| 'view-switch'
|
|
22
22
|
| 'environment-change'
|
|
23
23
|
| 'fog-change'
|
|
24
|
+
| 'time-discontinuity'
|
|
24
25
|
| 'device-recover'
|
|
25
26
|
| 'submit-failure';
|
|
26
27
|
|
|
@@ -43,6 +44,8 @@ export interface TemporalViewInput {
|
|
|
43
44
|
readonly previousUnjitteredViewProjection?: ArrayLike<number> | undefined;
|
|
44
45
|
readonly currentCameraPosition?: readonly [number, number, number] | undefined;
|
|
45
46
|
readonly previousCameraPosition?: readonly [number, number, number] | undefined;
|
|
47
|
+
/** Monotonic accepted sample time used to bridge failed render attempts. */
|
|
48
|
+
readonly sampleTimeSeconds?: number | undefined;
|
|
46
49
|
readonly resetReason?: TemporalResetReason | undefined;
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -65,6 +68,7 @@ interface TemporalViewSnapshot {
|
|
|
65
68
|
readonly previousUnjitteredViewProjection: ArrayLike<number> | undefined;
|
|
66
69
|
readonly currentCameraPosition: readonly [number, number, number] | undefined;
|
|
67
70
|
readonly previousCameraPosition: readonly [number, number, number] | undefined;
|
|
71
|
+
readonly sampleTimeSeconds: number | undefined;
|
|
68
72
|
readonly resetReason: TemporalResetReason | undefined;
|
|
69
73
|
}
|
|
70
74
|
|
|
@@ -83,6 +87,8 @@ export interface TemporalView {
|
|
|
83
87
|
/** Camera origins follow the same accepted-submit boundary as the matrices. */
|
|
84
88
|
readonly currentCameraPosition: readonly [number, number, number] | undefined;
|
|
85
89
|
readonly previousCameraPosition: readonly [number, number, number] | undefined;
|
|
90
|
+
/** Monotonic accepted sample time used to bridge failed render attempts. */
|
|
91
|
+
readonly sampleTimeSeconds: number | undefined;
|
|
86
92
|
readonly currentProjection: 'jittered' | 'unjittered';
|
|
87
93
|
readonly previousProjection: 'unjittered';
|
|
88
94
|
readonly historyRequired: boolean;
|
|
@@ -131,6 +137,7 @@ export function createTemporalView(input: TemporalViewInput): TemporalView {
|
|
|
131
137
|
previousUnjitteredViewProjection: input.previousUnjitteredViewProjection,
|
|
132
138
|
currentCameraPosition: input.currentCameraPosition,
|
|
133
139
|
previousCameraPosition: input.previousCameraPosition,
|
|
140
|
+
sampleTimeSeconds: input.sampleTimeSeconds,
|
|
134
141
|
resetReason: input.resetReason,
|
|
135
142
|
});
|
|
136
143
|
const taa = input.antialias === 'taa';
|
|
@@ -156,6 +163,7 @@ export function createTemporalView(input: TemporalViewInput): TemporalView {
|
|
|
156
163
|
previousUnjitteredViewProjection: input.previousUnjitteredViewProjection,
|
|
157
164
|
currentCameraPosition: input.currentCameraPosition,
|
|
158
165
|
previousCameraPosition: input.previousCameraPosition,
|
|
166
|
+
sampleTimeSeconds: input.sampleTimeSeconds,
|
|
159
167
|
currentProjection: taa ? 'jittered' : 'unjittered',
|
|
160
168
|
previousProjection: 'unjittered',
|
|
161
169
|
historyRequired: taa,
|
|
@@ -167,8 +175,11 @@ export function resolveTemporalReset(
|
|
|
167
175
|
previous: TemporalView | undefined,
|
|
168
176
|
next: TemporalView,
|
|
169
177
|
): TemporalResetReason | undefined {
|
|
170
|
-
|
|
171
|
-
|
|
178
|
+
// Motion Blur uses the unjittered `off` temporal mode as well as TAA. Keep
|
|
179
|
+
// the reset matrix shared so a camera switch, resize, or recovery cannot
|
|
180
|
+
// leak a previous motion vector merely because antialiasing is disabled.
|
|
181
|
+
if (previous === undefined) return 'first-frame';
|
|
182
|
+
if (next.mode === 'taa' && previous.mode !== 'taa') return 'first-frame';
|
|
172
183
|
const before = previous.input;
|
|
173
184
|
const after = next.input;
|
|
174
185
|
if (before.width !== after.width || before.height !== after.height) return 'resize';
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
composeSingleLayerMediumColor,
|
|
4
|
+
integrateSingleLayerMedium,
|
|
5
|
+
isBelowSingleLayerMediumPlane,
|
|
6
|
+
resolveSingleLayerMediumBackground,
|
|
7
|
+
} from '../single-layer-medium.js';
|
|
8
|
+
|
|
9
|
+
const coefficients = {
|
|
10
|
+
absorption: [0.2, 0.4, 0.8] as const,
|
|
11
|
+
scattering: [0.1, 0.1, 0.1] as const,
|
|
12
|
+
ior: 1.333,
|
|
13
|
+
phaseG: 0.4,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe('single-layer medium optics', () => {
|
|
17
|
+
it('uses Beer-Lambert transmission and the zero-extinction limit', () => {
|
|
18
|
+
const short = integrateSingleLayerMedium({ coefficients, distanceMeters: 1, cosTheta: 1 });
|
|
19
|
+
const long = integrateSingleLayerMedium({ coefficients, distanceMeters: 2, cosTheta: 1 });
|
|
20
|
+
expect(long.transmittance[0]).toBeLessThan(short.transmittance[0]);
|
|
21
|
+
expect(long.transmittance[1]).toBeLessThan(short.transmittance[1]);
|
|
22
|
+
expect(short.singleScatter[0]).toBeGreaterThan(0);
|
|
23
|
+
const empty = integrateSingleLayerMedium({
|
|
24
|
+
coefficients: { absorption: [0, 0, 0], scattering: [0, 0, 0], ior: 1.333 },
|
|
25
|
+
distanceMeters: 4,
|
|
26
|
+
cosTheta: 1,
|
|
27
|
+
});
|
|
28
|
+
expect(empty.transmittance).toEqual([1, 1, 1]);
|
|
29
|
+
expect(empty.singleScatter).toEqual([0, 0, 0]);
|
|
30
|
+
expect(empty.reflectance).toBeGreaterThan(0);
|
|
31
|
+
expect(empty.reflectance).toBeLessThan(1);
|
|
32
|
+
expect(
|
|
33
|
+
[...empty.transmittance, ...empty.singleScatter, empty.phase].every(Number.isFinite),
|
|
34
|
+
).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('keeps the zero-extinction limit and small-x RGB oracle continuous', () => {
|
|
38
|
+
const zeroExtinction = integrateSingleLayerMedium({
|
|
39
|
+
coefficients: {
|
|
40
|
+
absorption: [0, 0, 0],
|
|
41
|
+
scattering: [0, 0, 0],
|
|
42
|
+
ior: 1.333,
|
|
43
|
+
},
|
|
44
|
+
distanceMeters: 4,
|
|
45
|
+
cosTheta: 1,
|
|
46
|
+
});
|
|
47
|
+
expect(zeroExtinction.singleScatter).toEqual([0, 0, 0]);
|
|
48
|
+
|
|
49
|
+
const coefficients = {
|
|
50
|
+
absorption: [0, 0.000001, 0.25] as const,
|
|
51
|
+
scattering: [0.000001, 0.000001, 0.5] as const,
|
|
52
|
+
ior: 1.333,
|
|
53
|
+
};
|
|
54
|
+
const distanceMeters = 100000;
|
|
55
|
+
const optics = integrateSingleLayerMedium({
|
|
56
|
+
coefficients,
|
|
57
|
+
distanceMeters,
|
|
58
|
+
maxDistanceMeters: distanceMeters,
|
|
59
|
+
cosTheta: 1,
|
|
60
|
+
});
|
|
61
|
+
const sigmaT = [0.000001, 0.000002, 0.75];
|
|
62
|
+
const expected = sigmaT.map((extinction, index) => {
|
|
63
|
+
const x = extinction * distanceMeters;
|
|
64
|
+
const oneMinusExpNeg = x < 0.001 ? x * (1 - x / 2 + (x * x) / 6) : -Math.expm1(-x);
|
|
65
|
+
return ((coefficients.scattering[index] ?? 0) * oneMinusExpNeg) / extinction;
|
|
66
|
+
});
|
|
67
|
+
expect(optics.distanceMeters).toBe(distanceMeters);
|
|
68
|
+
expect(optics.singleScatter[0]).toBeCloseTo(expected[0] ?? 0, 12);
|
|
69
|
+
expect(optics.singleScatter[1]).toBeCloseTo(expected[1] ?? 0, 12);
|
|
70
|
+
expect(optics.singleScatter[2]).toBeCloseTo(expected[2] ?? 0, 12);
|
|
71
|
+
expect(optics.singleScatter.every(Number.isFinite)).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('allocates Fresnel once and keeps coverage/foam as finite mixing weights', () => {
|
|
75
|
+
const optics = integrateSingleLayerMedium({ coefficients, distanceMeters: 1.5, cosTheta: 0.4 });
|
|
76
|
+
const color = composeSingleLayerMediumColor({
|
|
77
|
+
optics,
|
|
78
|
+
background: [0.2, 0.3, 0.4],
|
|
79
|
+
reflection: [1, 1, 1],
|
|
80
|
+
foamColor: [0.9, 0.9, 0.9],
|
|
81
|
+
coverage: 0.8,
|
|
82
|
+
foam: 0.25,
|
|
83
|
+
});
|
|
84
|
+
expect(color.every(Number.isFinite)).toBe(true);
|
|
85
|
+
expect(color.every((channel) => channel >= 0)).toBe(true);
|
|
86
|
+
expect(
|
|
87
|
+
composeSingleLayerMediumColor({
|
|
88
|
+
optics,
|
|
89
|
+
background: [0, 0, 0],
|
|
90
|
+
reflection: [0, 0, 0],
|
|
91
|
+
coverage: 0,
|
|
92
|
+
}),
|
|
93
|
+
).toEqual([0, 0, 0]);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('keeps endpoint admission on the undisturbed plane under a strongly tilted ripple', () => {
|
|
97
|
+
const surfacePosition = [0, 0, 0] as const;
|
|
98
|
+
const endpoint = [1, -0.1, 0] as const;
|
|
99
|
+
expect(
|
|
100
|
+
isBelowSingleLayerMediumPlane({
|
|
101
|
+
surfacePosition,
|
|
102
|
+
geometricNormal: [0, 1, 0],
|
|
103
|
+
endpoint,
|
|
104
|
+
}),
|
|
105
|
+
).toBe(true);
|
|
106
|
+
// This shading normal would classify the same endpoint above water. It is
|
|
107
|
+
// deliberately excluded from the geometric-plane API and WGSL callsite.
|
|
108
|
+
expect(endpoint[0] * 0.995 + endpoint[1] * 0.1).toBeGreaterThan(0);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('keeps refracted color and depth paired and reports conservative fallbacks', () => {
|
|
112
|
+
const base = {
|
|
113
|
+
original: { color: [0.1, 0.2, 0.3] as const, depthMeters: 8, uv: [0.5, 0.5] as const },
|
|
114
|
+
surfaceDepthMeters: 2,
|
|
115
|
+
maxDistanceMeters: 20,
|
|
116
|
+
};
|
|
117
|
+
expect(
|
|
118
|
+
resolveSingleLayerMediumBackground({
|
|
119
|
+
...base,
|
|
120
|
+
refracted: { color: [0.4, 0.5, 0.6], depthMeters: 7, uv: [0.55, 0.5] },
|
|
121
|
+
}),
|
|
122
|
+
).toMatchObject({ source: 'refracted', distanceMeters: 5 });
|
|
123
|
+
expect(
|
|
124
|
+
resolveSingleLayerMediumBackground({
|
|
125
|
+
...base,
|
|
126
|
+
refracted: { color: [0.4, 0.5, 0.6], depthMeters: 1, uv: [0.55, 0.5] },
|
|
127
|
+
}),
|
|
128
|
+
).toMatchObject({ source: 'unrefracted', reason: 'front', color: base.original.color });
|
|
129
|
+
expect(
|
|
130
|
+
resolveSingleLayerMediumBackground({
|
|
131
|
+
...base,
|
|
132
|
+
refracted: { color: [0.4, 0.5, 0.6], depthMeters: 7, uv: [1.2, 0.5] },
|
|
133
|
+
}),
|
|
134
|
+
).toMatchObject({ source: 'unrefracted', reason: 'edge' });
|
|
135
|
+
expect(
|
|
136
|
+
resolveSingleLayerMediumBackground({
|
|
137
|
+
...base,
|
|
138
|
+
original: { color: [0, 0, 0], depthMeters: Number.NaN, uv: [0.5, 0.5] },
|
|
139
|
+
environment: [0.7, 0.8, 0.9],
|
|
140
|
+
}),
|
|
141
|
+
).toMatchObject({ source: 'environment', reason: 'sky-miss' });
|
|
142
|
+
expect(
|
|
143
|
+
resolveSingleLayerMediumBackground({
|
|
144
|
+
...base,
|
|
145
|
+
refracted: { color: [0.4, 0.5, 0.6], depthMeters: 7, uv: [-0.01, 0.5] },
|
|
146
|
+
}),
|
|
147
|
+
).toMatchObject({ source: 'unrefracted', reason: 'edge', color: base.original.color });
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from '@forgeax/engine-rhi-webgpu';
|
|
9
9
|
import { Transform } from '@forgeax/engine-scene';
|
|
10
10
|
import type { TextureAsset } from '@forgeax/engine-types';
|
|
11
|
-
import { describe, expect, it } from 'vitest';
|
|
11
|
+
import { afterAll, describe, expect, it } from 'vitest';
|
|
12
12
|
import {
|
|
13
13
|
Camera,
|
|
14
14
|
DirectionalLight,
|
|
@@ -32,17 +32,18 @@ const GPU_MAP_MODE_READ = 0x0001;
|
|
|
32
32
|
const TEST_REACTIVE = 0;
|
|
33
33
|
const LIGHTWEIGHT_DAWN = process.env.FORGEAX_DAWN_LIGHTWEIGHT === '1';
|
|
34
34
|
const ROSTER_SMOKE = process.env.FORGEAX_DAWN_ROSTER_SMOKE === '1';
|
|
35
|
-
const requestedSmokeFrames = Number.parseInt(process.env.SMOKE_MIN_FRAMES ?? '
|
|
35
|
+
const requestedSmokeFrames = Number.parseInt(process.env.SMOKE_MIN_FRAMES ?? '60', 10);
|
|
36
36
|
const ROSTER_SMOKE_FRAMES =
|
|
37
|
-
Number.isInteger(requestedSmokeFrames) && requestedSmokeFrames > 0 ? requestedSmokeFrames :
|
|
37
|
+
Number.isInteger(requestedSmokeFrames) && requestedSmokeFrames > 0 ? requestedSmokeFrames : 60;
|
|
38
38
|
|
|
39
39
|
const ENGINE_MANIFEST = await (async () => {
|
|
40
40
|
const { buildEngineShaderManifest } = await import('@forgeax/engine-vite-plugin-shader');
|
|
41
41
|
return buildEngineShaderManifest();
|
|
42
42
|
})();
|
|
43
|
-
const ENGINE_MANIFEST_URL =
|
|
44
|
-
JSON.stringify(ENGINE_MANIFEST),
|
|
45
|
-
)
|
|
43
|
+
const ENGINE_MANIFEST_URL = URL.createObjectURL(
|
|
44
|
+
new Blob([JSON.stringify(ENGINE_MANIFEST)], { type: 'application/json' }),
|
|
45
|
+
);
|
|
46
|
+
afterAll(() => URL.revokeObjectURL(ENGINE_MANIFEST_URL));
|
|
46
47
|
const DAWN_BACKEND: RhiBackendPack = {
|
|
47
48
|
rhi,
|
|
48
49
|
createShaderModule,
|
|
@@ -360,7 +361,7 @@ function luma(pixel: readonly [number, number, number, number]): number {
|
|
|
360
361
|
}
|
|
361
362
|
|
|
362
363
|
describe('Standard transmission Dawn ROI', () => {
|
|
363
|
-
it('completes a
|
|
364
|
+
it('completes a 60-frame transmission stream without renderer errors', async () => {
|
|
364
365
|
const result = await renderCase(
|
|
365
366
|
{
|
|
366
367
|
name: 'sustained-transmission',
|
|
@@ -372,9 +373,9 @@ describe('Standard transmission Dawn ROI', () => {
|
|
|
372
373
|
attenuationDistance: 2,
|
|
373
374
|
renderPath: 'forward',
|
|
374
375
|
},
|
|
375
|
-
|
|
376
|
+
60,
|
|
376
377
|
);
|
|
377
|
-
expect(result.framesObserved).toBe(
|
|
378
|
+
expect(result.framesObserved).toBe(60);
|
|
378
379
|
expect(result.errors).toEqual([]);
|
|
379
380
|
expect(result.observation).toBe(true);
|
|
380
381
|
expect(result.passNames).toContain('transmission-forward');
|
|
@@ -537,7 +538,7 @@ describe('Standard transmission Dawn ROI', () => {
|
|
|
537
538
|
}, 120_000);
|
|
538
539
|
|
|
539
540
|
if (ROSTER_SMOKE) {
|
|
540
|
-
it('emits the canonical
|
|
541
|
+
it('emits the canonical 60-frame Dawn roster receipt', async () => {
|
|
541
542
|
const result = await renderCase(
|
|
542
543
|
{
|
|
543
544
|
name: 'roster-stability',
|
|
@@ -551,7 +552,7 @@ describe('Standard transmission Dawn ROI', () => {
|
|
|
551
552
|
},
|
|
552
553
|
ROSTER_SMOKE_FRAMES,
|
|
553
554
|
);
|
|
554
|
-
expect(result.framesObserved).toBeGreaterThanOrEqual(
|
|
555
|
+
expect(result.framesObserved).toBeGreaterThanOrEqual(60);
|
|
555
556
|
expect(result.observation).toBe(true);
|
|
556
557
|
expect(result.errors).toEqual([]);
|
|
557
558
|
process.stdout.write(`[smoke] frames observed=${result.framesObserved}\n`);
|