@forgeax/engine-render 0.1.28 → 0.1.29
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 +627 -124
- package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
- package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/dynamic-geometry-host.d.ts +21 -0
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts +20 -0
- package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +3 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/gpu-driven-owner.d.ts +10 -0
- package/dist/assembly/gpu-driven-owner.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +8 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +7 -0
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material-shader-policy.d.ts +3 -1
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/recovery/failure-location.d.ts +12 -0
- package/dist/assembly/recovery/failure-location.d.ts.map +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts +6 -4
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts +5 -0
- package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -0
- package/dist/assembly/renderer-frame-transaction.d.ts +19 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-helpers.d.ts +3 -0
- package/dist/assembly/renderer-helpers.d.ts.map +1 -1
- package/dist/assembly/renderer-inspection.d.ts +4 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +6 -0
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
- package/dist/assembly/skin-palette-owner.d.ts +8 -0
- package/dist/assembly/skin-palette-owner.d.ts.map +1 -0
- package/dist/assembly/ssr-shader-prewarm.d.ts +6 -0
- package/dist/assembly/ssr-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/webgpu-device-loss.d.ts +15 -0
- package/dist/assembly/webgpu-device-loss.d.ts.map +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts +38 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready-mipmap.d.ts +11 -0
- package/dist/assembly/webgpu-ready-mipmap.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +7 -3
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts +10 -0
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-contract.d.ts +62 -0
- package/dist/assembly/webgpu-renderer-contract.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-guards.d.ts +9 -0
- package/dist/assembly/webgpu-renderer-guards.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-observation.d.ts +6 -0
- package/dist/assembly/webgpu-renderer-observation.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-recovery-failure.d.ts +12 -0
- package/dist/assembly/webgpu-renderer-recovery-failure.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +7 -141
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/assembly/webgpu-vertex-layouts.d.ts +28 -84
- package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
- package/dist/authoring.mjs +2 -2
- package/dist/{chunk-JAASCMXA.mjs → chunk-33XZFTQU.mjs} +245 -39
- package/dist/chunk-33XZFTQU.mjs.map +1 -0
- package/dist/{chunk-GF523LHF.mjs → chunk-BLXGONR2.mjs} +30 -12
- package/dist/chunk-BLXGONR2.mjs.map +1 -0
- package/dist/{chunk-J52NMQKR.mjs → chunk-BQVQOQJH.mjs} +1086 -838
- package/dist/chunk-BQVQOQJH.mjs.map +1 -0
- package/dist/{chunk-IQMKJLNU.mjs → chunk-BTWH7BP4.mjs} +386 -17
- package/dist/chunk-BTWH7BP4.mjs.map +1 -0
- package/dist/{chunk-MBU4ZVE7.mjs → chunk-FUODTTIA.mjs} +3921 -671
- package/dist/chunk-FUODTTIA.mjs.map +1 -0
- package/dist/{chunk-MYJ5RPJO.mjs → chunk-JQTSEI3Z.mjs} +3 -3
- package/dist/{chunk-MYJ5RPJO.mjs.map → chunk-JQTSEI3Z.mjs.map} +1 -1
- package/dist/{chunk-GE3SDD72.mjs → chunk-NICXSHAT.mjs} +16 -38
- package/dist/chunk-NICXSHAT.mjs.map +1 -0
- package/dist/{chunk-J6KACNOH.mjs → chunk-NRNXBLIJ.mjs} +577 -7
- package/dist/chunk-NRNXBLIJ.mjs.map +1 -0
- package/dist/{chunk-RBDBZ5R7.mjs → chunk-PA5DRJNI.mjs} +2 -2
- package/dist/chunk-PA5DRJNI.mjs.map +1 -0
- package/dist/{chunk-VSL23LZE.mjs → chunk-S4DNKQYQ.mjs} +1117 -445
- package/dist/chunk-S4DNKQYQ.mjs.map +1 -0
- package/dist/components/camera.d.ts +62 -2
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +6 -20
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/components/scene-instance.d.ts +2 -1
- package/dist/components/scene-instance.d.ts.map +1 -1
- package/dist/components/screen-space-reflection.d.ts +14 -0
- package/dist/components/screen-space-reflection.d.ts.map +1 -0
- package/dist/construct-renderer.mjs +12888 -7025
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +1 -12
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/environment/background.d.ts +6 -0
- package/dist/environment/background.d.ts.map +1 -0
- package/dist/errors/gpu-driven.d.ts +6 -3
- package/dist/errors/gpu-driven.d.ts.map +1 -1
- package/dist/errors/render.d.ts +7 -4
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +33 -3
- package/dist/extract/gpu-driven.d.ts.map +1 -1
- package/dist/features/host.d.ts +23 -1
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/noise-texture.d.ts +17 -0
- package/dist/features/noise-texture.d.ts.map +1 -0
- package/dist/features/plan.d.ts +83 -2
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +37 -4
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics-store.d.ts.map +1 -1
- package/dist/features/prepared-graphics.d.ts +5 -0
- package/dist/features/prepared-graphics.d.ts.map +1 -1
- package/dist/features/render-graph-compute.d.ts +5 -3
- package/dist/features/render-graph-compute.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +11 -3
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +19 -3
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/types.d.ts +11 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +2 -0
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +34 -1
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/pbr-program.d.ts +10 -0
- package/dist/gpu-driven/pbr-program.d.ts.map +1 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +144 -23
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/shadow-views.d.ts +126 -0
- package/dist/gpu-driven/shadow-views.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +18 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts +2 -8
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +14 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-texture-usage.d.ts +1 -0
- package/dist/gpu-texture-usage.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +6 -0
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/frame-resources.d.ts +8 -0
- package/dist/ibl/frame-resources.d.ts.map +1 -0
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +18 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +8 -8
- package/dist/inspection-types.d.ts +164 -0
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances-derived-bounds.d.ts +11 -0
- package/dist/instances-derived-bounds.d.ts.map +1 -1
- package/dist/instances.d.ts +89 -44
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.d.ts +3 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +117 -9
- package/dist/internal.mjs.map +1 -1
- package/dist/lifecycle.d.ts +2 -1
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/material-row.d.ts +5 -0
- package/dist/material-row.d.ts.map +1 -0
- package/dist/materials.d.ts +15 -0
- package/dist/materials.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +21 -5
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-output/auto-exposure/capability.d.ts +12 -0
- package/dist/pipeline/standard-output/auto-exposure/capability.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts +70 -0
- package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/graph.d.ts +75 -0
- package/dist/pipeline/standard-output/auto-exposure/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts +111 -0
- package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts +16 -0
- package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/preset.d.ts +14 -0
- package/dist/pipeline/standard-output/auto-exposure/preset.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/state.d.ts +46 -0
- package/dist/pipeline/standard-output/auto-exposure/state.d.ts.map +1 -0
- package/dist/pipeline/standard-output/color-transform.d.ts +27 -0
- package/dist/pipeline/standard-output/color-transform.d.ts.map +1 -0
- package/dist/pipeline/standard-output/graph.d.ts +15 -0
- package/dist/pipeline/standard-output/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-output/lut-admission.d.ts +29 -0
- package/dist/pipeline/standard-output/lut-admission.d.ts.map +1 -0
- package/dist/pipeline/standard-output/lut-gpu.d.ts +48 -0
- package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -0
- package/dist/pipeline/standard-output/lut-state.d.ts +68 -0
- package/dist/pipeline/standard-output/lut-state.d.ts.map +1 -0
- package/dist/pipeline/standard-output/resources.d.ts +10 -0
- package/dist/pipeline/standard-output/resources.d.ts.map +1 -0
- package/dist/pipeline/standard-output/types.d.ts +39 -0
- package/dist/pipeline/standard-output/types.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +2 -2
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +2 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec-types.d.ts +4 -0
- package/dist/pipeline-spec-types.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +1 -9
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/points-lines/standard-owner.d.ts +1 -1
- package/dist/points-lines/standard-owner.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +6 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/record/dynamic-geometry-consumption.d.ts +15 -0
- package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +3 -3
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +106 -5
- 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 +39 -4
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +7 -8
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +38 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +2 -10
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +12 -2
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +15 -6
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/prepared-material-bindings.d.ts +19 -0
- package/dist/record/prepared-material-bindings.d.ts.map +1 -0
- package/dist/record/recovery-pipeline.d.ts +2 -9
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +74 -26
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +62 -7
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +35 -7
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +1 -0
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +10 -2
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/recovery/render-system-roots.d.ts +11 -0
- package/dist/recovery/render-system-roots.d.ts.map +1 -0
- package/dist/recovery/types.d.ts +76 -0
- package/dist/recovery/types.d.ts.map +1 -0
- package/dist/reflection/record-owner.d.ts +0 -2
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +173 -30
- 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 +64 -5
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +7 -5
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +101 -41
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-projections.d.ts +22 -0
- package/dist/render-system-projections.d.ts.map +1 -0
- package/dist/render-system.d.ts +27 -77
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene-types.d.ts +14 -7
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +29 -11
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/shadow-visibility.d.ts +5 -0
- package/dist/scene/shadow-visibility.d.ts.map +1 -0
- package/dist/ssr/admission.d.ts +70 -1
- package/dist/ssr/admission.d.ts.map +1 -1
- package/dist/ssr/compose.d.ts +13 -0
- package/dist/ssr/compose.d.ts.map +1 -0
- package/dist/ssr/errors.d.ts +35 -0
- package/dist/ssr/errors.d.ts.map +1 -1
- package/dist/ssr/graph.d.ts +60 -0
- package/dist/ssr/graph.d.ts.map +1 -0
- package/dist/ssr/history.d.ts +97 -0
- package/dist/ssr/history.d.ts.map +1 -0
- package/dist/ssr/hiz.d.ts +37 -0
- package/dist/ssr/hiz.d.ts.map +1 -0
- package/dist/ssr/inspection.d.ts +42 -0
- package/dist/ssr/inspection.d.ts.map +1 -0
- package/dist/ssr/resources.d.ts +58 -0
- package/dist/ssr/resources.d.ts.map +1 -0
- package/dist/ssr/temporal.d.ts +38 -0
- package/dist/ssr/temporal.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +32 -10
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/systems/skin-palette-types.d.ts +15 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -1
- package/dist/systems/transparent-dispatch.d.ts +9 -0
- package/dist/systems/transparent-dispatch.d.ts.map +1 -0
- package/dist/targets/material-source.d.ts +7 -0
- package/dist/targets/material-source.d.ts.map +1 -1
- package/dist/temporal/frame-coordinator.d.ts +7 -0
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts +8 -0
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/history.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -6
- package/dist/temporal/inspection.d.ts.map +1 -1
- package/dist/temporal/standard-scene-data.d.ts +2 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/temporal-view.d.ts +2 -0
- package/dist/temporal/temporal-view.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +35 -1
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +3 -1
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/temporal.d.ts +6 -0
- package/dist/volume/temporal.d.ts.map +1 -1
- package/package.json +21 -20
- package/src/__tests__/auto-exposure-gpu-evidence.ts +291 -0
- package/src/__tests__/auto-exposure-inspection.unit.test.ts +80 -0
- package/src/__tests__/auto-exposure-transaction.integration.test.ts +99 -0
- package/src/__tests__/auto-exposure.browser.test.ts +33 -0
- package/src/__tests__/auto-exposure.dawn.test.ts +33 -0
- package/src/__tests__/detached-inspection.integration.test.ts +5 -0
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +18 -0
- package/src/__tests__/device-scope-stale-matrix.unit.test.ts +18 -0
- package/src/__tests__/docs-gate-green.unit.test.ts +3 -3
- package/src/__tests__/factory-contract.integration.test.ts +67 -8
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +19 -0
- package/src/__tests__/feature-depth-input.dawn.test.ts +121 -0
- package/src/__tests__/feature-noise.unit.test.ts +38 -0
- package/src/__tests__/fixtures/taa-resolve-pinned-baseline.wgsl +301 -0
- package/src/__tests__/frame-camera-selection.unit.test.ts +131 -0
- package/src/__tests__/frame-plan-contract.unit.test.ts +24 -0
- package/src/__tests__/frame-targets.unit.test.ts +24 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +3 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +79 -0
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +287 -6
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +122 -142
- package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +10 -1
- package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +264 -0
- package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +349 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1417 -0
- package/src/__tests__/gpu-driven-pbr.integration.test.ts +21 -0
- package/src/__tests__/gpu-driven-production-fixture.ts +96 -0
- package/src/__tests__/gpu-driven-production.integration.test.ts +1075 -93
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +1 -3
- package/src/__tests__/gpu-driven-shadow-views.browser.test.ts +63 -0
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +294 -0
- package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +97 -0
- package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +168 -0
- package/src/__tests__/gpu-driven-skin-contract.test-d.ts +11 -0
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +72 -20
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +30 -9
- package/src/__tests__/gpu-driven-view.unit.test.ts +159 -52
- package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -1
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +42 -0
- package/src/__tests__/gpu-scene-render-graph-gpu.ts +19 -5
- package/src/__tests__/gpu-scene.dawn.test.ts +40 -13
- package/src/__tests__/gpu-scene.unit.test.ts +559 -33
- package/src/__tests__/instances-culling.integration.test.ts +36 -10
- package/src/__tests__/instances-derived-bounds.unit.test.ts +54 -0
- package/src/__tests__/instances-store.unit.test.ts +242 -39
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +6 -0
- package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +13 -16
- package/src/__tests__/lut-lkg-transaction.integration.test.ts +122 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +5 -6
- package/src/__tests__/material-dispatch-shader-id.unit.test.ts +51 -0
- package/src/__tests__/material-lane-selection.unit.test.ts +60 -0
- package/src/__tests__/material-numeric-upload.unit.test.ts +53 -0
- package/src/__tests__/material-texture-handles.unit.test.ts +18 -0
- package/src/__tests__/material-texture-source.unit.test.ts +87 -0
- package/src/__tests__/materials-authoring-validation.unit.test.ts +41 -0
- package/src/__tests__/materials-standard-contract.unit.test.ts +52 -2
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
- package/src/__tests__/normal-fallback.dawn.test.ts +122 -0
- package/src/__tests__/particle-material-input-layout.unit.test.ts +104 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +37 -3
- package/src/__tests__/pipeline-texture-specialization.unit.test.ts +138 -0
- package/src/__tests__/point-shadow-inspection.unit.test.ts +2 -0
- package/src/__tests__/prepared-gpu-driven-pbr-contract.test-d.ts +31 -0
- package/src/__tests__/prepared-gpu-driven-pbr-contract.unit.test.ts +39 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +35 -4
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +21 -0
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +6 -2
- package/src/__tests__/profiler-phase-catalog.test.ts +5 -0
- package/src/__tests__/public-surface.test-d.ts +3 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +30 -12
- package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +104 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +2 -1
- package/src/__tests__/render-error-code-owner.test-d.ts +4 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +22 -0
- package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
- package/src/__tests__/render-feature-gpu-work.integration.test.ts +285 -2
- package/src/__tests__/render-feature-plan.unit.test.ts +245 -0
- package/src/__tests__/render-feature-shadow-order.unit.test.ts +228 -0
- package/src/__tests__/render-feature-zero-work.unit.test.ts +35 -1
- package/src/__tests__/render-graph-fallback.integration.test.ts +2 -2
- package/src/__tests__/render-owner-cohesion.unit.test.ts +55 -0
- package/src/__tests__/render-scene-mixed-updates.integration.test.ts +426 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +914 -23
- package/src/__tests__/render-scene-resource-updates.integration.test.ts +214 -0
- package/src/__tests__/render-scene-skin-lifecycle.integration.test.ts +173 -0
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +133 -0
- package/src/__tests__/render-target-material-source.test-d.ts +27 -3
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +60 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
- package/src/__tests__/shader-manifest-fixture.ts +39 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +0 -33
- package/src/__tests__/skin-palette-persistent.integration.test.ts +28 -0
- package/src/__tests__/skin-palette-persistent.unit.test.ts +247 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +118 -14
- package/src/__tests__/specular-environment-scale.dawn.test.ts +156 -0
- package/src/__tests__/ssr-admission-matrix.integration.test.ts +7 -1
- package/src/__tests__/ssr-confidence-compose.unit.test.ts +84 -0
- package/src/__tests__/ssr-coordinate-oracle.unit.test.ts +28 -0
- package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +91 -0
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +112 -0
- package/src/__tests__/ssr-gpu-dispatch.ts +946 -0
- package/src/__tests__/ssr-graph-topology.unit.test.ts +104 -0
- package/src/__tests__/ssr-history-filter.dawn.test.ts +198 -0
- package/src/__tests__/ssr-hit-color.dawn.test.ts +273 -0
- package/src/__tests__/ssr-hiz-odd-reduction.dawn.test.ts +569 -0
- package/src/__tests__/ssr-hiz-rescue.dawn.test.ts +279 -0
- package/src/__tests__/ssr-hiz.browser.test.ts +150 -0
- package/src/__tests__/ssr-hiz.dawn.test.ts +150 -0
- package/src/__tests__/ssr-hiz.unit.test.ts +56 -0
- package/src/__tests__/ssr-inspection.unit.test.ts +105 -0
- package/src/__tests__/ssr-memory-budget.unit.test.ts +45 -0
- package/src/__tests__/ssr-performance-sequence-aggregation.unit.test.ts +15 -0
- package/src/__tests__/ssr-public-surface.test-d.ts +37 -0
- package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +387 -0
- package/src/__tests__/ssr-reflection-mip-reducer.dawn.test.ts +309 -0
- package/src/__tests__/ssr-reprojection-probe.ts +90 -0
- package/src/__tests__/ssr-roughness-mip.dawn.test.ts +163 -0
- package/src/__tests__/ssr-shader-prewarm.unit.test.ts +59 -0
- package/src/__tests__/ssr-spatial.integration.test.ts +141 -0
- package/src/__tests__/ssr-stable-lattice.dawn.test.ts +475 -0
- package/src/__tests__/ssr-temporal-history.unit.test.ts +202 -0
- package/src/__tests__/ssr-texel-crossing.dawn.test.ts +448 -0
- package/src/__tests__/ssr-zero-work.integration.test.ts +87 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +44 -12
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +29 -0
- package/src/__tests__/standard-output-chain-contract.unit.test.ts +99 -0
- package/src/__tests__/standard-output-chain.integration.test.ts +73 -0
- package/src/__tests__/standard-output-gpu-evidence.ts +205 -0
- package/src/__tests__/standard-output.browser.test.ts +15 -0
- package/src/__tests__/standard-output.dawn.test.ts +15 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +38 -0
- package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
- package/src/__tests__/standard-profile-oracle.unit.test.ts +22 -0
- package/src/__tests__/standard-surface-lighting.unit.test.ts +41 -0
- package/src/__tests__/standard-texture-specialization.dawn.test.ts +141 -0
- package/src/__tests__/surface-adjacent-regressions.integration.test.ts +6 -3
- package/src/__tests__/taa-coverage-edge.dawn.test.ts +193 -0
- package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
- package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +778 -0
- package/src/__tests__/taa-stability-feedback.browser.test.ts +23 -0
- package/src/__tests__/taa-stability-feedback.dawn.test.ts +68 -0
- package/src/__tests__/taa-stability-feedback.ts +341 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +49 -7
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +9 -0
- package/src/__tests__/temporal-transaction.integration.test.ts +28 -0
- package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +109 -4
- package/src/__tests__/typed-scene-pass-material-cache.integration.test.ts +126 -0
- package/src/__tests__/vertex-layouts-ssot.unit.test.ts +47 -0
- package/src/__tests__/visibility-extract.perf.test.ts +20 -8
- package/src/__tests__/visibility-instances.integration.test.ts +19 -7
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +20 -9
- package/src/assembly/atmosphere-shader-prewarm.ts +38 -0
- package/src/assembly/dynamic-geometry-host.ts +48 -0
- package/src/assembly/dynamic-geometry-runtime.ts +71 -0
- package/src/assembly/factory.ts +4 -0
- package/src/assembly/gpu-driven-owner.ts +29 -0
- package/src/assembly/host-contract.ts +10 -0
- package/src/assembly/material/assembly.ts +38 -0
- package/src/assembly/material-shader-policy.ts +71 -28
- package/src/assembly/recovery/failure-location.ts +62 -0
- package/src/assembly/recovery/renderer-recover.ts +19 -17
- package/src/assembly/renderer-facade.ts +12 -0
- package/src/assembly/renderer-feature-inspection.ts +13 -0
- package/src/assembly/renderer-frame-transaction.ts +63 -0
- package/src/assembly/renderer-helpers.ts +26 -0
- package/src/assembly/renderer-inspection.ts +6 -0
- package/src/assembly/shader-prewarm-policy.ts +32 -0
- package/src/assembly/skin-palette-owner.ts +21 -0
- package/src/assembly/ssr-shader-prewarm.ts +41 -0
- package/src/assembly/webgpu-device-loss.ts +75 -0
- package/src/assembly/webgpu-pbr-ready.ts +232 -0
- package/src/assembly/webgpu-ready-mipmap.ts +26 -0
- package/src/assembly/webgpu-ready.ts +142 -121
- package/src/assembly/webgpu-renderer-bootstrap.ts +85 -0
- package/src/assembly/webgpu-renderer-contract.ts +69 -0
- package/src/assembly/webgpu-renderer-guards.ts +32 -0
- package/src/assembly/webgpu-renderer-observation.ts +43 -0
- package/src/assembly/webgpu-renderer-recovery-failure.ts +62 -0
- package/src/assembly/webgpu-renderer.ts +666 -652
- package/src/assembly/webgpu-vertex-layouts.ts +233 -87
- package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
- package/src/components/camera.ts +287 -7
- package/src/components/index.ts +1 -0
- package/src/components/instances.ts +45 -18
- package/src/components/scene-instance.ts +2 -1
- package/src/components/screen-space-reflection.ts +21 -0
- package/src/components/sprite-animation.ts +2 -2
- package/src/components/sprite-instances.ts +1 -1
- package/src/device/gpu-residency.ts +34 -31
- package/src/environment/background.ts +263 -0
- package/src/errors/gpu-driven.ts +39 -5
- package/src/errors/render.ts +27 -3
- package/src/extract/camera.ts +26 -1
- package/src/extract/gpu-driven.ts +185 -10
- package/src/features/host.ts +237 -19
- package/src/features/noise-texture.ts +91 -0
- package/src/features/plan.ts +553 -24
- package/src/features/prepared-gpu-work.ts +631 -49
- package/src/features/prepared-graphics-store.ts +31 -0
- package/src/features/prepared-graphics.ts +5 -0
- package/src/features/render-graph-compute.ts +41 -8
- package/src/features/render-graph-contribution.ts +141 -3
- package/src/features/render-graph-raster.ts +143 -30
- package/src/features/types.ts +11 -0
- package/src/fullscreen-post-process-pass.ts +3 -0
- package/src/gpu-driven/batch-topology.ts +424 -102
- package/src/gpu-driven/pbr-program.ts +31 -0
- package/src/gpu-driven/prepared-draw.ts +29 -4
- package/src/gpu-driven/production-raster.ts +2267 -694
- package/src/gpu-driven/shadow-views.ts +539 -0
- package/src/gpu-driven/view-gpu.ts +188 -41
- package/src/gpu-scene-schema.ts +52 -11
- package/src/gpu-scene.ts +186 -99
- package/src/gpu-texture-usage.ts +1 -0
- package/src/hdrp-buffers.ts +72 -36
- package/src/ibl/frame-resources.ts +38 -0
- package/src/ibl/skylight-bind-group.ts +5 -4
- package/src/index.ts +109 -1
- package/src/inspection-types.ts +191 -0
- package/src/instances-derived-bounds.ts +258 -34
- package/src/instances.ts +459 -150
- package/src/internal.ts +22 -0
- package/src/lifecycle.ts +2 -0
- package/src/material-row.ts +145 -0
- package/src/materials.ts +44 -8
- package/src/pbr-pipeline.ts +159 -17
- package/src/pipeline/standard-forward-lane.ts +52 -24
- package/src/pipeline/standard-output/__tests__/lut-admission.unit.test.ts +103 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/capability.unit.test.ts +40 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/gpu.contract.unit.test.ts +125 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/graph.contract.unit.test.ts +94 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/oracle.test.ts +108 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/preset.test.ts +26 -0
- package/src/pipeline/standard-output/auto-exposure/capability.ts +38 -0
- package/src/pipeline/standard-output/auto-exposure/gpu.ts +567 -0
- package/src/pipeline/standard-output/auto-exposure/graph.ts +221 -0
- package/src/pipeline/standard-output/auto-exposure/inspection.ts +231 -0
- package/src/pipeline/standard-output/auto-exposure/oracle.ts +291 -0
- package/src/pipeline/standard-output/auto-exposure/preset.ts +28 -0
- package/src/pipeline/standard-output/auto-exposure/state.ts +156 -0
- package/src/pipeline/standard-output/color-transform.ts +124 -0
- package/src/pipeline/standard-output/graph.ts +139 -0
- package/src/pipeline/standard-output/lut-admission.ts +121 -0
- package/src/pipeline/standard-output/lut-gpu.ts +399 -0
- package/src/pipeline/standard-output/lut-state.ts +176 -0
- package/src/pipeline/standard-output/resources.ts +121 -0
- package/src/pipeline/standard-output/types.ts +58 -0
- package/src/pipeline/standard-pipeline.ts +192 -59
- package/src/pipeline/standard-post.ts +186 -27
- package/src/pipeline-builder.ts +16 -6
- package/src/pipeline-spec-types.ts +4 -0
- package/src/pipeline-spec.ts +37 -29
- package/src/points-lines/standard-owner.ts +6 -14
- package/src/prepare/prepared-graphics-resolver.ts +9 -2
- package/src/record/__tests__/material-slot-plan.unit.test.ts +48 -0
- package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +2 -29
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +36 -5
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +45 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +5 -0
- package/src/record/dynamic-geometry-consumption.ts +59 -0
- package/src/record/frame-lighting.ts +12 -11
- package/src/record/frame-snapshot.ts +133 -23
- package/src/record/frame-targets.ts +9 -0
- package/src/record/frame.ts +725 -133
- package/src/record/main-pass-geometry.ts +149 -94
- package/src/record/main-pass-material.ts +115 -26
- package/src/record/main-pass-sprite-draws.ts +16 -107
- package/src/record/main-pass.ts +78 -8
- package/src/record/material-uniforms.ts +1 -1
- package/src/record/mesh-ssbo.ts +59 -15
- package/src/record/prepared-material-bindings.ts +234 -0
- package/src/record/recovery-pipeline.ts +59 -136
- package/src/record/render-context.ts +90 -22
- package/src/record/shadow-pass.ts +1231 -209
- package/src/record/skybox-post-pass.ts +14 -3
- package/src/record/typed-frame-graph.ts +1004 -44
- package/src/record/view-ubo.ts +11 -0
- package/src/recovery/render-system-candidate.ts +90 -66
- package/src/recovery/render-system-roots.ts +113 -0
- package/src/recovery/types.ts +77 -0
- package/src/reflection/record-owner.ts +26 -54
- package/src/render-contract.ts +195 -25
- package/src/render-graph-primitives.ts +6 -2
- package/src/render-pipeline.ts +70 -1
- package/src/render-system-extract-tail.ts +409 -160
- package/src/render-system-extract.ts +376 -102
- package/src/render-system-projections.ts +241 -0
- package/src/render-system.ts +681 -822
- package/src/scene/render-scene-types.ts +13 -4
- package/src/scene/render-scene.ts +569 -355
- package/src/scene/shadow-visibility.ts +21 -0
- package/src/ssr/admission.ts +380 -14
- package/src/ssr/compose.ts +144 -0
- package/src/ssr/errors.ts +48 -0
- package/src/ssr/graph.ts +777 -0
- package/src/ssr/history.ts +436 -0
- package/src/ssr/hiz.ts +124 -0
- package/src/ssr/inspection.ts +124 -0
- package/src/ssr/resources.ts +202 -0
- package/src/ssr/temporal.ts +164 -0
- package/src/systems/skin-palette-allocator.ts +495 -148
- package/src/systems/skin-palette-types.ts +17 -0
- package/src/systems/transparent-dispatch.ts +90 -0
- package/src/targets/material-source.ts +34 -0
- package/src/temporal/coverage.ts +1 -1
- package/src/temporal/frame-coordinator.ts +23 -2
- package/src/temporal/gpu.ts +74 -12
- package/src/temporal/history.ts +3 -1
- package/src/temporal/inspection.ts +2 -1
- package/src/temporal/standard-scene-data.ts +3 -1
- package/src/temporal/temporal-view.ts +3 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +204 -139
- package/src/typed-render-graph-primitives.ts +266 -74
- package/src/typed-shadow-passes.ts +122 -12
- package/src/volume/temporal.ts +10 -0
- package/dist/chunk-GE3SDD72.mjs.map +0 -1
- package/dist/chunk-GF523LHF.mjs.map +0 -1
- package/dist/chunk-IQMKJLNU.mjs.map +0 -1
- package/dist/chunk-J52NMQKR.mjs.map +0 -1
- package/dist/chunk-J6KACNOH.mjs.map +0 -1
- package/dist/chunk-JAASCMXA.mjs.map +0 -1
- package/dist/chunk-MBU4ZVE7.mjs.map +0 -1
- package/dist/chunk-RBDBZ5R7.mjs.map +0 -1
- package/dist/chunk-VSL23LZE.mjs.map +0 -1
- package/src/__tests__/instances-world-ownership.integration.test.ts +0 -62
- package/src/scene/__tests__/changed-block-summary.candidate.test.ts +0 -36
|
@@ -5,7 +5,7 @@ import { HANDLE_CUBE } from '@forgeax/engine-assets-runtime';
|
|
|
5
5
|
import { World } from '@forgeax/engine-ecs';
|
|
6
6
|
import { createProfiler } from '@forgeax/engine-profiler';
|
|
7
7
|
import { DEFAULT_STANDARD_PROFILE } from '@forgeax/engine-render';
|
|
8
|
-
import { RhiError, type ShaderModule } from '@forgeax/engine-rhi';
|
|
8
|
+
import { RhiError, type RhiWebgpuRuntimeCause, type ShaderModule } from '@forgeax/engine-rhi';
|
|
9
9
|
import {
|
|
10
10
|
RhiNullAdapter,
|
|
11
11
|
RhiNullCommandEncoder,
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
Camera as LocalCamera,
|
|
28
28
|
TONEMAP_ACES_FILMIC,
|
|
29
29
|
} from '../components/camera';
|
|
30
|
+
import { TemporalFrameSubmitError } from '../errors/render';
|
|
30
31
|
import type { RenderFeature } from '../features/types';
|
|
31
32
|
import { renderLifecycleManifestUrl } from './shader-manifest-fixture';
|
|
32
33
|
|
|
@@ -144,6 +145,54 @@ describe('factory contract', () => {
|
|
|
144
145
|
expect(profiler.phaseCatalog.render).toEqual([]);
|
|
145
146
|
});
|
|
146
147
|
|
|
148
|
+
it('preserves a PipelineSpecError and its structured GPU cause during initialization', async () => {
|
|
149
|
+
const original = RhiNullDevice.prototype.createRenderPipeline;
|
|
150
|
+
const failure = new RhiError({
|
|
151
|
+
code: 'webgpu-runtime-error',
|
|
152
|
+
expected: 'the GPU accepts the pre-warmed render pipeline descriptor',
|
|
153
|
+
hint: 'inspect the backend gpuMessage for the rejected descriptor',
|
|
154
|
+
});
|
|
155
|
+
let injected = false;
|
|
156
|
+
const operation = vi.spyOn(RhiNullDevice.prototype, 'createRenderPipeline');
|
|
157
|
+
operation.mockImplementation(function (this: RhiNullDevice, ...args: never[]) {
|
|
158
|
+
if (!injected) {
|
|
159
|
+
injected = true;
|
|
160
|
+
return err(failure) as never;
|
|
161
|
+
}
|
|
162
|
+
return Reflect.apply(original as (...input: never[]) => unknown, this, args) as never;
|
|
163
|
+
} as never);
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const renderer = await constructRenderer(
|
|
167
|
+
{ getContext: () => null },
|
|
168
|
+
{ rhi },
|
|
169
|
+
{ shaderManifestUrl: renderLifecycleManifestUrl() },
|
|
170
|
+
);
|
|
171
|
+
const ready = await renderer.initialization;
|
|
172
|
+
expect(injected).toBe(true);
|
|
173
|
+
expect(ready.ok).toBe(false);
|
|
174
|
+
if (ready.ok) return;
|
|
175
|
+
expect(ready.error).toMatchObject({
|
|
176
|
+
code: 'webgpu-runtime-error',
|
|
177
|
+
detail: {
|
|
178
|
+
error: {
|
|
179
|
+
code: 'pipeline-build-failed',
|
|
180
|
+
detail: { cause: failure },
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
await renderer.dispose();
|
|
185
|
+
} finally {
|
|
186
|
+
operation.mockRestore();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('keeps named temporal causes assignable without flattening their detail', () => {
|
|
191
|
+
const temporal = new TemporalFrameSubmitError('queue-submit-failed');
|
|
192
|
+
const cause: RhiWebgpuRuntimeCause = temporal;
|
|
193
|
+
expect(cause.detail).toEqual({ reason: 'queue-submit-failed' });
|
|
194
|
+
});
|
|
195
|
+
|
|
147
196
|
it('forwards timing admission to the backend device request', async () => {
|
|
148
197
|
const adapter = new RhiNullAdapter();
|
|
149
198
|
const device = (await adapter.requestDevice()).unwrap();
|
|
@@ -178,6 +227,7 @@ describe('factory contract', () => {
|
|
|
178
227
|
{ rhi },
|
|
179
228
|
{ shaderManifestUrl: manifestUrl() },
|
|
180
229
|
);
|
|
230
|
+
expect((await renderer.initialization).ok).toBe(true);
|
|
181
231
|
const world = new World();
|
|
182
232
|
const attached = renderer.attach(world);
|
|
183
233
|
expect(attached.ok).toBe(true);
|
|
@@ -228,11 +278,13 @@ describe('factory contract', () => {
|
|
|
228
278
|
// Before the first draw there is no committed graph from which to
|
|
229
279
|
// claim an output transform or an intermediate target. Inspection is
|
|
230
280
|
// intentionally conservative instead of projecting profile defaults.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
281
|
+
output: {
|
|
282
|
+
displayEncoded: false,
|
|
283
|
+
surfaceStorage: expect.any(String),
|
|
284
|
+
surfaceDisplay: expect.any(String),
|
|
285
|
+
endpoint: 'surface.storage.raw',
|
|
286
|
+
capability: 'unavailable',
|
|
287
|
+
},
|
|
236
288
|
observation: {
|
|
237
289
|
observationId: expect.any(String),
|
|
238
290
|
frameId: expect.any(Number),
|
|
@@ -250,6 +302,7 @@ describe('factory contract', () => {
|
|
|
250
302
|
{ rhi },
|
|
251
303
|
{ shaderManifestUrl: manifestUrl() },
|
|
252
304
|
);
|
|
305
|
+
expect((await renderer.initialization).ok).toBe(true);
|
|
253
306
|
const target = renderer.createRenderTarget({
|
|
254
307
|
shape: '2d',
|
|
255
308
|
width: 17,
|
|
@@ -312,6 +365,7 @@ describe('factory contract', () => {
|
|
|
312
365
|
{ rhi, features: [feature] },
|
|
313
366
|
{ shaderManifestUrl: manifestUrl() },
|
|
314
367
|
);
|
|
368
|
+
expect((await renderer.initialization).ok).toBe(true);
|
|
315
369
|
const world = new World();
|
|
316
370
|
const attached = renderer.attach(world);
|
|
317
371
|
expect(attached.ok).toBe(true);
|
|
@@ -474,7 +528,11 @@ describe('factory contract', () => {
|
|
|
474
528
|
);
|
|
475
529
|
expect((await renderer.initialization).ok).toBe(true);
|
|
476
530
|
const errors: string[] = [];
|
|
477
|
-
const
|
|
531
|
+
const errorDetails: unknown[] = [];
|
|
532
|
+
const unsubscribe = renderer.onError((error) => {
|
|
533
|
+
errors.push(error.code);
|
|
534
|
+
errorDetails.push(error);
|
|
535
|
+
});
|
|
478
536
|
const world = new World();
|
|
479
537
|
const attached = renderer.attach(world);
|
|
480
538
|
expect(attached.ok).toBe(true);
|
|
@@ -516,7 +574,7 @@ describe('factory contract', () => {
|
|
|
516
574
|
camera: { lease: attached.value },
|
|
517
575
|
environment: { lease: attached.value },
|
|
518
576
|
});
|
|
519
|
-
expect(frame.ok).toBe(true);
|
|
577
|
+
expect(frame.ok, JSON.stringify(errorDetails)).toBe(true);
|
|
520
578
|
expect(renderer.inspect().standardLighting).toMatchObject({
|
|
521
579
|
producer: 'none',
|
|
522
580
|
requested: 0,
|
|
@@ -611,6 +669,7 @@ describe('factory contract', () => {
|
|
|
611
669
|
{ rhi },
|
|
612
670
|
{ shaderManifestUrl: manifest },
|
|
613
671
|
);
|
|
672
|
+
expect((await renderer.initialization).ok).toBe(true);
|
|
614
673
|
expect(renderer.releaseSurface().ok).toBe(true);
|
|
615
674
|
expect(renderer.releaseSurface().ok).toBe(true);
|
|
616
675
|
expect(renderer.draw([], { cameraOwner: 0, resourceOwner: 0 }).ok).toBe(false);
|
|
@@ -15,4 +15,23 @@ describe('fallback texture row-stride owner', () => {
|
|
|
15
15
|
expect(rendererSource).toContain('FALLBACK_BYTES_PER_ROW');
|
|
16
16
|
expect(rendererSource).not.toMatch(/const FALLBACK_BYTES_PER_ROW\s*=\s*256/);
|
|
17
17
|
});
|
|
18
|
+
|
|
19
|
+
it('uploads an exactly neutral normal instead of treating 128/255 as one half', () => {
|
|
20
|
+
const creation = rendererSource.slice(
|
|
21
|
+
rendererSource.indexOf('const fallbackNormalTextureResult ='),
|
|
22
|
+
rendererSource.indexOf('const fallbackNormalTextureViewResult ='),
|
|
23
|
+
);
|
|
24
|
+
expect(creation).toContain("format: 'rgba16float'");
|
|
25
|
+
const start = creation.indexOf('const fallbackNormalPixel =');
|
|
26
|
+
const end = creation.indexOf('const fallbackNormalWriteResult =');
|
|
27
|
+
// Execute the actual owner payload construction; do not duplicate its bytes.
|
|
28
|
+
const bytes = new Function(
|
|
29
|
+
'FALLBACK_BYTES_PER_ROW',
|
|
30
|
+
`${creation.slice(start, end)}; return fallbackNormalPixel;`,
|
|
31
|
+
)(FALLBACK_BYTES_PER_ROW) as Uint8Array;
|
|
32
|
+
const values = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
33
|
+
expect([0, 1, 2, 3].map((i) => values.getUint16(i * 2, true))).toEqual([
|
|
34
|
+
0x3800, 0x3800, 0x3c00, 0x3c00,
|
|
35
|
+
]);
|
|
36
|
+
});
|
|
18
37
|
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { RenderGraphBuilder } from '@forgeax/engine-render-graph';
|
|
2
|
+
import type { RhiCommandEncoder } from '@forgeax/engine-rhi';
|
|
3
|
+
import { createShaderModule, rhi } from '@forgeax/engine-rhi-webgpu';
|
|
4
|
+
import { ok } from '@forgeax/engine-types';
|
|
5
|
+
import { expect, it } from 'vitest';
|
|
6
|
+
import { createRenderFeatureGpuWorkOwner } from '../features/prepared-gpu-work';
|
|
7
|
+
import { RenderFeatureComputeGraphProjection } from '../features/render-graph-compute';
|
|
8
|
+
import { createRenderFeatureTarget } from '../features/targets';
|
|
9
|
+
|
|
10
|
+
it('samples this frame graph depth after its producer on the real GPU', async () => {
|
|
11
|
+
const adapter = (await rhi.requestAdapter()).unwrap();
|
|
12
|
+
const device = (await adapter.requestDevice()).unwrap();
|
|
13
|
+
const code = `@group(0) @binding(0) var depth: texture_depth_2d;
|
|
14
|
+
@group(0) @binding(1) var<storage, read_write> output: array<f32>;
|
|
15
|
+
@compute @workgroup_size(1) fn sample() { output[0] = textureLoad(depth, vec2<i32>(0), 0); }`;
|
|
16
|
+
const shader = (await createShaderModule(device, { code })).unwrap();
|
|
17
|
+
const owner = createRenderFeatureGpuWorkOwner({
|
|
18
|
+
getDevice: () => device,
|
|
19
|
+
getShaderModuleFactory: () => ({ createShaderModule: () => ok(shader) }),
|
|
20
|
+
});
|
|
21
|
+
const session = owner.beginFeature('depth-input', 0);
|
|
22
|
+
const program = session
|
|
23
|
+
.prepareProgram('sample', {
|
|
24
|
+
wgsl: code,
|
|
25
|
+
entryPoints: ['sample'],
|
|
26
|
+
bindings: [
|
|
27
|
+
{
|
|
28
|
+
entries: [
|
|
29
|
+
{ binding: 0, visibility: 4, texture: { sampleType: 'depth' } },
|
|
30
|
+
{ binding: 1, visibility: 4, buffer: { type: 'storage' } },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
})
|
|
35
|
+
.unwrap();
|
|
36
|
+
const output = session
|
|
37
|
+
.prepareBuffer('output', { size: 4, usage: ['storage', 'copy-src'] })
|
|
38
|
+
.unwrap();
|
|
39
|
+
const fallbackTexture = device
|
|
40
|
+
.createTexture({
|
|
41
|
+
size: { width: 1, height: 1 },
|
|
42
|
+
format: 'depth32float',
|
|
43
|
+
usage: 0x04 | 0x10,
|
|
44
|
+
textureBindingViewDimension: undefined,
|
|
45
|
+
})
|
|
46
|
+
.unwrap();
|
|
47
|
+
const fallback = device.createTextureView(fallbackTexture, {}).unwrap();
|
|
48
|
+
const depth = session
|
|
49
|
+
.prepareTextureView(
|
|
50
|
+
'depth',
|
|
51
|
+
fallback,
|
|
52
|
+
createRenderFeatureTarget({ kind: 'scene-depth', format: 'depth32float', sampleCount: 1 }),
|
|
53
|
+
)
|
|
54
|
+
.unwrap();
|
|
55
|
+
const bindings = session
|
|
56
|
+
.prepareBindings('bindings', {
|
|
57
|
+
program,
|
|
58
|
+
entries: [
|
|
59
|
+
{ binding: 0, resource: { kind: 'texture-view', reference: depth } },
|
|
60
|
+
{ binding: 1, buffer: output },
|
|
61
|
+
],
|
|
62
|
+
})
|
|
63
|
+
.unwrap();
|
|
64
|
+
const work = session
|
|
65
|
+
.resolveComputePass('depth-input', {
|
|
66
|
+
program,
|
|
67
|
+
bindings,
|
|
68
|
+
dispatches: [{ entryPoint: 'sample', workgroups: [1] }],
|
|
69
|
+
})
|
|
70
|
+
.unwrap();
|
|
71
|
+
const source = session.resolveBuffer(output);
|
|
72
|
+
if (source === undefined) throw new Error('Missing output buffer');
|
|
73
|
+
const readback = device.createBuffer({ size: 4, usage: 0x01 | 0x08 }).unwrap();
|
|
74
|
+
try {
|
|
75
|
+
for (const expected of [0.25, 0.75]) {
|
|
76
|
+
const graph = new RenderGraphBuilder<{ readonly encoder: RhiCommandEncoder }>();
|
|
77
|
+
const texture = graph
|
|
78
|
+
.createTexture('current-depth', {
|
|
79
|
+
format: 'depth32float',
|
|
80
|
+
size: { width: 1, height: 1 },
|
|
81
|
+
})
|
|
82
|
+
.unwrap();
|
|
83
|
+
const view = graph.view(texture).unwrap();
|
|
84
|
+
graph
|
|
85
|
+
.addRasterPass('depth-producer', {
|
|
86
|
+
colorAttachments: [],
|
|
87
|
+
depthStencilAttachment: {
|
|
88
|
+
view,
|
|
89
|
+
depthLoadOp: 'clear',
|
|
90
|
+
depthStoreOp: 'store',
|
|
91
|
+
depthClearValue: expected,
|
|
92
|
+
},
|
|
93
|
+
accesses: [{ resource: view, usage: 'depth-stencil-write' }],
|
|
94
|
+
encode: () => {},
|
|
95
|
+
})
|
|
96
|
+
.unwrap();
|
|
97
|
+
const projection = new RenderFeatureComputeGraphProjection(
|
|
98
|
+
graph,
|
|
99
|
+
undefined,
|
|
100
|
+
undefined,
|
|
101
|
+
() => ({ texture, view }),
|
|
102
|
+
);
|
|
103
|
+
projection.addPass('sample', 'depth-input', 0, work).unwrap();
|
|
104
|
+
const compiled = graph.compile({ device, surfaceSize: { width: 1, height: 1 } }).unwrap();
|
|
105
|
+
const encoder = device.createCommandEncoder().unwrap();
|
|
106
|
+
compiled.execute({ encoder }).unwrap();
|
|
107
|
+
encoder.copyBufferToBuffer(source.buffer, 0, readback, 0, 4);
|
|
108
|
+
device.queue.submit([encoder.finish().unwrap()]).unwrap();
|
|
109
|
+
await device.queue.onSubmittedWorkDone();
|
|
110
|
+
const mapped = (await readback.mapAsync(1)).unwrap();
|
|
111
|
+
const actual = new DataView(mapped.getMappedRange().unwrap()).getFloat32(0, true);
|
|
112
|
+
mapped.unmap();
|
|
113
|
+
expect(actual).toBeCloseTo(expected, 6);
|
|
114
|
+
await compiled.retire();
|
|
115
|
+
}
|
|
116
|
+
} finally {
|
|
117
|
+
owner.dispose().unwrap();
|
|
118
|
+
device.destroyBuffer(readback).unwrap();
|
|
119
|
+
device.destroyTexture(fallbackTexture).unwrap();
|
|
120
|
+
}
|
|
121
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { RhiDevice, Texture, TextureView } from '@forgeax/engine-rhi';
|
|
2
|
+
import { ok } from '@forgeax/engine-types';
|
|
3
|
+
import { expect, it } from 'vitest';
|
|
4
|
+
import { createFeatureNoisePixels, createFeatureNoiseTexture } from '../features/noise-texture';
|
|
5
|
+
|
|
6
|
+
it('provides deterministic spatial and channel variation instead of a uniform fallback', () => {
|
|
7
|
+
const pixels = createFeatureNoisePixels();
|
|
8
|
+
expect(pixels).toEqual(createFeatureNoisePixels());
|
|
9
|
+
expect(pixels).toHaveLength(64 * 64 * 4);
|
|
10
|
+
for (let channel = 0; channel < 4; channel++) {
|
|
11
|
+
const values = pixels.filter((_, index) => index % 4 === channel);
|
|
12
|
+
expect(new Set(values).size).toBe(256);
|
|
13
|
+
expect(values.reduce((sum, value) => sum + value, 0) / values.length).toBeGreaterThan(120);
|
|
14
|
+
expect(values.reduce((sum, value) => sum + value, 0) / values.length).toBeLessThan(135);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('returns the generation-owned texture together with its view after upload', () => {
|
|
19
|
+
const texture = { id: 'noise-texture' } as unknown as Texture;
|
|
20
|
+
const view = { id: 'noise-view' } as unknown as TextureView;
|
|
21
|
+
let writes = 0;
|
|
22
|
+
const device = {
|
|
23
|
+
createTexture: () => ok(texture),
|
|
24
|
+
createTextureView: () => ok(view),
|
|
25
|
+
destroyTexture: () => ok(undefined),
|
|
26
|
+
queue: {
|
|
27
|
+
writeTexture: () => {
|
|
28
|
+
writes += 1;
|
|
29
|
+
return ok(undefined);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
} as unknown as RhiDevice;
|
|
33
|
+
|
|
34
|
+
const result = createFeatureNoiseTexture(device);
|
|
35
|
+
expect(result.ok).toBe(true);
|
|
36
|
+
if (result.ok) expect(result.value).toEqual({ texture, view });
|
|
37
|
+
expect(writes).toBe(1);
|
|
38
|
+
});
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
// Pinned test-only baseline for taa-neighborhood-equivalence.dawn.test.ts.
|
|
2
|
+
// Copied from packages/shader/src/taa-resolve.wgsl at commit fc641abefbdc07a074d2b8473b52b37bcb26f85d.
|
|
3
|
+
// SHA-256 (source body): 4a7a7c7def9cb860da2a92ad960aa6be1d41d6c6551e0e77093cd5d2cc99ea9d.
|
|
4
|
+
// This fixture is intentionally immutable when production TAA changes.
|
|
5
|
+
#define_import_path forgeax_view::taa_resolve
|
|
6
|
+
|
|
7
|
+
// Keep the fragment input shape explicit for compilers that tree-shake imported
|
|
8
|
+
// type declarations before resolving the vertex entry point.
|
|
9
|
+
struct FullscreenOutput {
|
|
10
|
+
@builtin(position) position : vec4<f32>,
|
|
11
|
+
@location(0) uv : vec2<f32>,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
fn fullscreen_triangle(vertex_index : u32) -> FullscreenOutput {
|
|
15
|
+
var x : f32 = -1.0;
|
|
16
|
+
var y : f32 = -1.0;
|
|
17
|
+
if (vertex_index == 1u) {
|
|
18
|
+
x = 3.0;
|
|
19
|
+
}
|
|
20
|
+
if (vertex_index == 2u) {
|
|
21
|
+
y = 3.0;
|
|
22
|
+
}
|
|
23
|
+
let u : f32 = (x + 1.0) * 0.5;
|
|
24
|
+
let v : f32 = 1.0 - (y + 1.0) * 0.5;
|
|
25
|
+
var out : FullscreenOutput;
|
|
26
|
+
out.position = vec4<f32>(x, y, 0.0, 1.0);
|
|
27
|
+
out.uv = vec2<f32>(u, v);
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
struct TaaResolveParams {
|
|
32
|
+
currentJitterUv : vec2<f32>,
|
|
33
|
+
historyValid : u32,
|
|
34
|
+
temporalFrameIndex : u32,
|
|
35
|
+
hasSecondaryReactivity : u32,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
struct TaaResolveOutput {
|
|
39
|
+
@location(0) color : vec4<f32>,
|
|
40
|
+
@location(1) temporal : vec4<f32>,
|
|
41
|
+
@location(2) stability : f32,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
@group(1) @binding(0) var currentColor : texture_2d<f32>;
|
|
45
|
+
@group(1) @binding(1) var currentSampler : sampler;
|
|
46
|
+
@group(1) @binding(2) var historyColor : texture_2d<f32>;
|
|
47
|
+
@group(1) @binding(3) var historySampler : sampler;
|
|
48
|
+
@group(1) @binding(4) var historyTemporal : texture_2d<f32>;
|
|
49
|
+
@group(1) @binding(5) var temporalSampler : sampler;
|
|
50
|
+
@group(1) @binding(6) var currentTemporal : texture_2d<f32>;
|
|
51
|
+
@group(1) @binding(7) var currentTemporalSampler : sampler;
|
|
52
|
+
@group(1) @binding(8) var<uniform> params : TaaResolveParams;
|
|
53
|
+
@group(1) @binding(9) var historyStability : texture_2d<f32>;
|
|
54
|
+
@group(1) @binding(10) var secondaryReactivity : texture_2d<f32>;
|
|
55
|
+
|
|
56
|
+
fn sampleSecondaryReactivity(uv : vec2<f32>) -> f32 {
|
|
57
|
+
if (params.hasSecondaryReactivity == 0u) { return 0.0; }
|
|
58
|
+
let size = vec2<i32>(textureDimensions(secondaryReactivity));
|
|
59
|
+
let center = vec2<i32>(uv * vec2<f32>(size));
|
|
60
|
+
var reactive = 0.0;
|
|
61
|
+
// Conservatively cover the reconstruction footprint, including producers
|
|
62
|
+
// on a reduced-resolution lattice. Never interpolate a motion flag away.
|
|
63
|
+
for (var y = -3; y <= 3; y++) {
|
|
64
|
+
for (var x = -3; x <= 3; x++) {
|
|
65
|
+
let pixel = clamp(center + vec2<i32>(x, y), vec2<i32>(0), size - vec2<i32>(1));
|
|
66
|
+
let value = textureLoad(secondaryReactivity, pixel, 0).r;
|
|
67
|
+
if (value != value || abs(value) > 3.402823e+38) { return 1.0; }
|
|
68
|
+
reactive = max(reactive, clamp(value, 0.0, 1.0));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return reactive;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// One complete eight-phase jitter cycle must settle after motion/rejection.
|
|
75
|
+
// Store the state in a private r8unorm attachment; temporal-v1's
|
|
76
|
+
// reactive lane includes secondary-source changes; receiver velocity and depth
|
|
77
|
+
// remain unchanged for downstream effects such as Motion Blur.
|
|
78
|
+
const TAA_STABILITY_FRAMES : f32 = 8.0;
|
|
79
|
+
const TAA_HISTORY_SETTLE_FRAMES : f32 = 128.0;
|
|
80
|
+
|
|
81
|
+
fn taaStableAge(previous : f32, accepted : bool, temporal : vec4<f32>, priorMotion : vec2<f32>) -> f32 {
|
|
82
|
+
let stationary = max(length(temporal.xy), length(priorMotion)) < 1e-5;
|
|
83
|
+
let count = min(floor(clamp(previous, 0.0, 1.0) * 255.0 + 0.5), TAA_HISTORY_SETTLE_FRAMES);
|
|
84
|
+
return select(0.0, min(count + 1.0, TAA_HISTORY_SETTLE_FRAMES), accepted && temporal.w == 0.0 && stationary);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
fn rgbToYCoCg(rgb : vec3<f32>) -> vec3<f32> {
|
|
88
|
+
return vec3<f32>(
|
|
89
|
+
dot(rgb, vec3<f32>(0.25, 0.5, 0.25)),
|
|
90
|
+
dot(rgb, vec3<f32>(0.5, 0.0, -0.5)),
|
|
91
|
+
dot(rgb, vec3<f32>(-0.25, 0.5, -0.25)),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fn yCoCgToRgb(value : vec3<f32>) -> vec3<f32> {
|
|
96
|
+
return vec3<f32>(value.x + value.y - value.z, value.x + value.z, value.x - value.y - value.z);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
fn luminance(rgb : vec3<f32>) -> f32 {
|
|
100
|
+
return dot(rgb, vec3<f32>(0.2126, 0.7152, 0.0722));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
fn taaAccumulationWeight(frameIndex : u32, steadyWeight : f32) -> f32 {
|
|
104
|
+
let samples = f32(frameIndex);
|
|
105
|
+
return min(steadyWeight, samples / (samples + 1.0));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Karis, High Quality Temporal Supersampling (SIGGRAPH 2014), slide 20.
|
|
109
|
+
// With linear luminance, these normalized weights are equivalent to
|
|
110
|
+
// T(C)=C/(1+luma(C)), temporal blending, then T^-1(C)=C/(1-luma(C)).
|
|
111
|
+
// One scalar per color preserves chroma and avoids an unstable explicit
|
|
112
|
+
// inverse near one. History and the post-processing output remain HDR.
|
|
113
|
+
fn blendTaaHistory(current : vec3<f32>, history : vec3<f32>, historyWeight : f32) -> vec3<f32> {
|
|
114
|
+
let currentWeight = (1.0 - historyWeight) / (1.0 + max(0.0, luminance(current)));
|
|
115
|
+
let previousWeight = historyWeight / (1.0 + max(0.0, luminance(history)));
|
|
116
|
+
return (current * currentWeight + history * previousWeight) / max(currentWeight + previousWeight, 0.00001);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Render-target FP16 conversion can consistently round down. Feeding that
|
|
120
|
+
// error back every frame darkens history, increasingly so at high weights.
|
|
121
|
+
// Choose between the two exactly representable neighbors without bias before
|
|
122
|
+
// the attachment conversion. One shared RGB threshold preserves neutral color;
|
|
123
|
+
// frame/pixel hashing avoids locking rounding to the eight jitter phases.
|
|
124
|
+
fn taaRoundingNoise(pixel : vec2<u32>, frame : u32) -> f32 {
|
|
125
|
+
var bits = pixel.x * 0x9e3779b9u + pixel.y * 0x85ebca6bu + frame * 0xc2b2ae35u;
|
|
126
|
+
bits = (bits ^ (bits >> 16u)) * 0x7feb352du;
|
|
127
|
+
bits = (bits ^ (bits >> 15u)) * 0x846ca68bu;
|
|
128
|
+
bits = bits ^ (bits >> 16u);
|
|
129
|
+
return f32(bits >> 8u) / 16777216.0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
fn roundTaaHistory(color : vec3<f32>, noise : f32) -> vec3<f32> {
|
|
133
|
+
let magnitude = min(abs(color), vec3<f32>(65504.0));
|
|
134
|
+
let exponent = (bitcast<vec3<u32>>(magnitude) >> vec3<u32>(23u)) & vec3<u32>(255u);
|
|
135
|
+
// Normal spacing is 2^(exponent - 127 - 10); subnormals use 2^-24.
|
|
136
|
+
let step = bitcast<vec3<f32>>((max(exponent, vec3<u32>(113u)) - vec3<u32>(10u)) << vec3<u32>(23u));
|
|
137
|
+
let scaled = magnitude / step;
|
|
138
|
+
let integral = floor(scaled);
|
|
139
|
+
let rounded = (integral + select(vec3<f32>(0.0), vec3<f32>(1.0), vec3<f32>(noise) < scaled - integral)) * step;
|
|
140
|
+
return select(rounded, -rounded, color < vec3<f32>(0.0));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
struct TaaCurrentTemporal {
|
|
144
|
+
temporal : vec4<f32>,
|
|
145
|
+
depthEdge : bool,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
fn closestCurrentTemporal(pixel : vec2<i32>, dimensions : vec2<i32>) -> TaaCurrentTemporal {
|
|
149
|
+
let clamped = clamp(pixel, vec2<i32>(0), dimensions - vec2<i32>(1));
|
|
150
|
+
var closest = textureLoad(currentTemporal, clamped, 0);
|
|
151
|
+
var farthestDepth = closest.z;
|
|
152
|
+
var hasBackground = closest.z < 0.0;
|
|
153
|
+
// Jitter changes coverage at silhouettes and subpixel gaps. Select the
|
|
154
|
+
// nearest valid surface in the reconstruction footprint, carrying its
|
|
155
|
+
// motion and reactive flag together. The negative clear depth is absent
|
|
156
|
+
// geometry, not a surface closer than every real sample.
|
|
157
|
+
for (var y = -1; y <= 1; y++) {
|
|
158
|
+
for (var x = -1; x <= 1; x++) {
|
|
159
|
+
let samplePixel = clamp(pixel + vec2<i32>(x, y), vec2<i32>(0), dimensions - vec2<i32>(1));
|
|
160
|
+
let candidate = textureLoad(currentTemporal, samplePixel, 0);
|
|
161
|
+
hasBackground = hasBackground || candidate.z < 0.0;
|
|
162
|
+
farthestDepth = max(farthestDepth, candidate.z);
|
|
163
|
+
if (candidate.z >= 0.0 && (closest.z < 0.0 || candidate.z < closest.z)) {
|
|
164
|
+
closest = candidate;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Three.js TRAA exempts current depth edges from the disocclusion test.
|
|
169
|
+
// Use the existing logarithmic-depth tolerance, not a perspective threshold.
|
|
170
|
+
return TaaCurrentTemporal(closest, closest.z >= 0.0 &&
|
|
171
|
+
(hasBackground || farthestDepth - closest.z > 0.0025 + closest.z * 0.01));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
fn taaNeighborhood(uv : vec2<f32>, current : vec3<f32>, settled : bool) -> array<vec3<f32>, 25> {
|
|
175
|
+
let dimensions = vec2<i32>(textureDimensions(currentColor));
|
|
176
|
+
let pixel = vec2<i32>(uv * vec2<f32>(dimensions));
|
|
177
|
+
var samples : array<vec3<f32>, 25>;
|
|
178
|
+
var index = 0u;
|
|
179
|
+
// The symmetric union of the 3x3 bilinear supports stays centered across
|
|
180
|
+
// subpixel jitter signs. A 4x4 box anchored to floor(uv*size-0.5) shifts by
|
|
181
|
+
// one texel at zero jitter, periodically clipping otherwise valid history.
|
|
182
|
+
// During motion retain the eight nearest neighbors plus current only.
|
|
183
|
+
for (var y = -2; y <= 2; y++) {
|
|
184
|
+
for (var x = -2; x <= 2; x++) {
|
|
185
|
+
let delta = vec2<i32>(x, y);
|
|
186
|
+
if (!settled && (any(abs(delta) > vec2<i32>(1)) || all(delta == vec2<i32>(0)))) {
|
|
187
|
+
samples[index] = current;
|
|
188
|
+
} else {
|
|
189
|
+
samples[index] = textureLoad(currentColor, clamp(pixel + vec2<i32>(x, y), vec2<i32>(0), dimensions - vec2<i32>(1)), 0).rgb;
|
|
190
|
+
}
|
|
191
|
+
index++;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return samples;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
fn clipTaaHistory(current : vec3<f32>, neighbors : array<vec3<f32>, 25>, history : vec3<f32>) -> vec3<f32> {
|
|
198
|
+
// Build bounds in the clipping space. Transforming RGB extrema is invalid:
|
|
199
|
+
// the chroma axes contain negative coefficients and can collapse or invert.
|
|
200
|
+
var clipMin = rgbToYCoCg(current);
|
|
201
|
+
var clipMax = clipMin;
|
|
202
|
+
for (var i = 0u; i < 25u; i++) {
|
|
203
|
+
let sample = rgbToYCoCg(neighbors[i]);
|
|
204
|
+
clipMin = min(clipMin, sample);
|
|
205
|
+
clipMax = max(clipMax, sample);
|
|
206
|
+
}
|
|
207
|
+
return yCoCgToRgb(clamp(rgbToYCoCg(history), clipMin, clipMax));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
struct TaaClipDecision {
|
|
211
|
+
history : vec3<f32>,
|
|
212
|
+
state : f32,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
fn resolveTaaClipping(clipped : vec3<f32>, history : vec3<f32>, previous : f32, age : f32) -> TaaClipDecision {
|
|
216
|
+
// Codes 0..128 are accepted stationary age. The remaining 42 codes store
|
|
217
|
+
// 1..7 consecutive misses in one of six signed RGB directions. Reversing
|
|
218
|
+
// direction or finding support breaks the streak, so one dark jitter phase
|
|
219
|
+
// cannot erase the accumulated coverage of a thin bright surface. Eight
|
|
220
|
+
// persistent misses restore clipping even without motion. Color clipping
|
|
221
|
+
// must not invalidate the accepted geometric reconstruction footprint.
|
|
222
|
+
if (age < TAA_HISTORY_SETTLE_FRAMES) {
|
|
223
|
+
// Release phase-local clipping while accumulation is still responsive.
|
|
224
|
+
// Waiting until the 0.99 history weight has engaged locks in the earlier
|
|
225
|
+
// clipped mean and makes a static image drift for hundreds more frames.
|
|
226
|
+
return TaaClipDecision(mix(clipped, history, smoothstep(TAA_STABILITY_FRAMES, 64.0, age)), age / 255.0);
|
|
227
|
+
}
|
|
228
|
+
let delta = clipped - history;
|
|
229
|
+
let magnitude = abs(delta);
|
|
230
|
+
var axis = 0u;
|
|
231
|
+
if (magnitude.y > magnitude.x) { axis = 1u; }
|
|
232
|
+
if (magnitude.z > magnitude[axis]) { axis = 2u; }
|
|
233
|
+
let scale = max(1.0, max(abs(history.x), max(abs(history.y), abs(history.z))));
|
|
234
|
+
if (magnitude[axis] <= scale * 0.00001) {
|
|
235
|
+
return TaaClipDecision(history, TAA_HISTORY_SETTLE_FRAMES / 255.0);
|
|
236
|
+
}
|
|
237
|
+
let direction = axis * 2u + select(0u, 1u, delta[axis] > 0.0);
|
|
238
|
+
let code = u32(floor(clamp(previous, 0.0, 1.0) * 255.0 + 0.5));
|
|
239
|
+
var streak = 1u;
|
|
240
|
+
if (code >= 129u && code <= 170u) {
|
|
241
|
+
let prior = code - 129u;
|
|
242
|
+
if (prior / 7u == direction) { streak = prior % 7u + 2u; }
|
|
243
|
+
}
|
|
244
|
+
if (streak >= 8u) { return TaaClipDecision(clipped, TAA_HISTORY_SETTLE_FRAMES / 255.0); }
|
|
245
|
+
return TaaClipDecision(history, f32(129u + direction * 7u + streak - 1u) / 255.0);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
@vertex
|
|
249
|
+
fn vs_main(@builtin(vertex_index) vertexIndex : u32) -> FullscreenOutput {
|
|
250
|
+
return fullscreen_triangle(vertexIndex);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
fn fs_taa_resolve(in : FullscreenOutput) -> TaaResolveOutput {
|
|
254
|
+
let dimensions = vec2<i32>(textureDimensions(currentColor, 0));
|
|
255
|
+
let currentUv = in.uv + params.currentJitterUv;
|
|
256
|
+
let current = textureSampleLevel(currentColor, currentSampler, currentUv, 0.0);
|
|
257
|
+
let pixel = vec2<i32>(currentUv * vec2<f32>(dimensions));
|
|
258
|
+
let currentSample = closestCurrentTemporal(pixel, dimensions);
|
|
259
|
+
let sceneTemporal = currentSample.temporal;
|
|
260
|
+
let temporal = vec4<f32>(sceneTemporal.xyz,
|
|
261
|
+
max(sceneTemporal.w, sampleSecondaryReactivity(currentUv)));
|
|
262
|
+
let historyUv = in.uv - temporal.xy;
|
|
263
|
+
let historyInBounds = all(historyUv >= vec2<f32>(0.0)) && all(historyUv <= vec2<f32>(1.0));
|
|
264
|
+
let history = textureSampleLevel(historyColor, historySampler, historyUv, 0.0);
|
|
265
|
+
let previousTemporal = textureSampleLevel(historyTemporal, temporalSampler, historyUv, 0.0);
|
|
266
|
+
let depthDelta = abs(previousTemporal.z - temporal.z);
|
|
267
|
+
let depthThreshold = 0.0025 + temporal.z * 0.01;
|
|
268
|
+
let rejected =
|
|
269
|
+
params.historyValid == 0u ||
|
|
270
|
+
!historyInBounds ||
|
|
271
|
+
temporal.z < 0.0 ||
|
|
272
|
+
((previousTemporal.z < 0.0 || depthDelta > depthThreshold) && !currentSample.depthEdge);
|
|
273
|
+
let historyPixel = clamp(vec2<i32>(historyUv * vec2<f32>(dimensions)), vec2<i32>(0), dimensions - vec2<i32>(1));
|
|
274
|
+
let priorStability = textureLoad(historyStability, historyPixel, 0).r;
|
|
275
|
+
let stableAge = taaStableAge(priorStability, !rejected, temporal, previousTemporal.xy);
|
|
276
|
+
let clipped = clipTaaHistory(current.rgb, taaNeighborhood(currentUv, current.rgb, stableAge >= TAA_STABILITY_FRAMES), history.rgb);
|
|
277
|
+
let clipping = resolveTaaClipping(clipped, history.rgb, priorStability, stableAge);
|
|
278
|
+
let clippedHistoryRgb = clipping.history;
|
|
279
|
+
let reactiveFactor = 1.0 - clamp(temporal.w, 0.0, 1.0);
|
|
280
|
+
let velocityFactor = 1.0 - clamp(length(temporal.xy) * 64.0, 0.0, 1.0);
|
|
281
|
+
// Motion ending is not the same as settled radiance. Keep fast recovery
|
|
282
|
+
// for 64 stationary frames before reducing the residual jitter response.
|
|
283
|
+
// Any rejection, receiver motion, or secondary reactivity resets this age.
|
|
284
|
+
let steadyWeight = mix(0.95, 0.99, smoothstep(64.0, TAA_HISTORY_SETTLE_FRAMES, stableAge));
|
|
285
|
+
let progressiveWeight = taaAccumulationWeight(params.temporalFrameIndex, steadyWeight);
|
|
286
|
+
// Depth is a disocclusion gate, not a continuous history fade. A sloped
|
|
287
|
+
// static surface changes sampled depth under jitter without changing its
|
|
288
|
+
// identity; attenuating accepted history makes those edges oscillate.
|
|
289
|
+
let historyWeight = progressiveWeight * reactiveFactor * velocityFactor;
|
|
290
|
+
let resolved = select(blendTaaHistory(current.rgb, clippedHistoryRgb, historyWeight), current.rgb, rejected);
|
|
291
|
+
return TaaResolveOutput(
|
|
292
|
+
vec4<f32>(roundTaaHistory(resolved, taaRoundingNoise(vec2<u32>(in.position.xy), params.temporalFrameIndex)), current.a),
|
|
293
|
+
temporal,
|
|
294
|
+
clipping.state,
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@fragment
|
|
299
|
+
fn fs_main(in : FullscreenOutput) -> TaaResolveOutput {
|
|
300
|
+
return fs_taa_resolve(in);
|
|
301
|
+
}
|