@forgeax/engine-render 0.1.7 → 0.1.20
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 +140 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/assembly/backend-contract.d.ts +12 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/factory.d.ts +26 -5
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +4 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/renderer-frame-transaction.d.ts +39 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -0
- package/dist/assembly/renderer-inspection.d.ts +22 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -0
- package/dist/assembly/renderer-lifecycle.d.ts +4 -0
- package/dist/assembly/renderer-lifecycle.d.ts.map +1 -0
- package/dist/authoring.mjs +4 -2
- package/dist/authoring.mjs.map +1 -1
- package/dist/chunk-4XINDLAY.mjs +9404 -0
- package/dist/chunk-4XINDLAY.mjs.map +1 -0
- package/dist/chunk-CDTWTHZR.mjs +752 -0
- package/dist/chunk-CDTWTHZR.mjs.map +1 -0
- package/dist/chunk-FJ6P52EE.mjs +46 -0
- package/dist/chunk-FJ6P52EE.mjs.map +1 -0
- package/dist/chunk-JDWARUOI.mjs +44 -0
- package/dist/chunk-JDWARUOI.mjs.map +1 -0
- package/dist/chunk-M2MP4ZOU.mjs +73 -0
- package/dist/chunk-M2MP4ZOU.mjs.map +1 -0
- package/dist/chunk-PCHBPYML.mjs +385 -0
- package/dist/chunk-PCHBPYML.mjs.map +1 -0
- package/dist/chunk-RXZ3RGOU.mjs +53 -0
- package/dist/chunk-RXZ3RGOU.mjs.map +1 -0
- package/dist/{chunk-YEJIUW7D.mjs → chunk-TBQJOK2L.mjs} +356 -543
- package/dist/chunk-TBQJOK2L.mjs.map +1 -0
- package/dist/{chunk-CQXZC5XI.mjs → chunk-VFPLTKCU.mjs} +79 -69
- package/dist/chunk-VFPLTKCU.mjs.map +1 -0
- package/dist/components/atmosphere.d.ts +9 -0
- package/dist/components/atmosphere.d.ts.map +1 -0
- package/dist/components/camera.d.ts +2 -1
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/fog.d.ts +8 -0
- package/dist/components/fog.d.ts.map +1 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/motion-blur.d.ts +7 -0
- package/dist/components/motion-blur.d.ts.map +1 -0
- package/dist/components/spot-light.d.ts +12 -0
- package/dist/components/spot-light.d.ts.map +1 -1
- package/dist/construct-renderer.d.ts +2 -2
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +11146 -14507
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/device-scope.d.ts +4 -0
- package/dist/device/device-scope.d.ts.map +1 -1
- package/dist/device/gpu-residency.d.ts +19 -2
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/environment/frame.d.ts +60 -0
- package/dist/environment/frame.d.ts.map +1 -0
- package/dist/environment/generation.d.ts +21 -0
- package/dist/environment/generation.d.ts.map +1 -0
- package/dist/environment/graph.d.ts +4 -0
- package/dist/environment/graph.d.ts.map +1 -0
- package/dist/environment/inspection.d.ts +48 -0
- package/dist/environment/inspection.d.ts.map +1 -0
- package/dist/environment/lifecycle.d.ts +39 -0
- package/dist/environment/lifecycle.d.ts.map +1 -0
- package/dist/environment/signature.d.ts +25 -0
- package/dist/environment/signature.d.ts.map +1 -0
- package/dist/errors/render.d.ts +204 -1
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/camera.d.ts +5 -0
- package/dist/extract/camera.d.ts.map +1 -0
- package/dist/extract/environment.d.ts +74 -0
- package/dist/extract/environment.d.ts.map +1 -0
- package/dist/extract/visibility.d.ts +1 -1
- package/dist/extract/visibility.d.ts.map +1 -1
- package/dist/features/host.d.ts +9 -2
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-feature.d.ts +16 -0
- package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -0
- package/dist/features/motion-blur/motion-blur-params.d.ts +25 -0
- package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -0
- package/dist/features/plan.d.ts +17 -2
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +3 -1
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics.d.ts +2 -1
- package/dist/features/prepared-graphics.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +2 -1
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/targets.d.ts +3 -0
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +12 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +7 -1
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +2 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-usage.d.ts +2 -0
- package/dist/gpu-usage.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +5 -6
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +24 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +6 -4
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +43 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +2 -0
- package/dist/light-buffer-layout.d.ts +20 -12
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts +22 -0
- package/dist/materials.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +16 -9
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts +3 -0
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +48 -0
- package/dist/pipeline/standard-post.d.ts.map +1 -0
- package/dist/pipeline/standard-profile.d.ts +12 -2
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +18 -0
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/record/frame-lighting.d.ts +2 -0
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +137 -6
- 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 +6 -3
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-timing.d.ts +32 -0
- package/dist/record/gpu-timing.d.ts.map +1 -0
- package/dist/record/main-pass-geometry.d.ts +11 -0
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +9 -6
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +8 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +81 -19
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +1 -11
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +36 -4
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +4 -1
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/render-contract.d.ts +157 -8
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-data.d.ts +10 -6
- package/dist/render-data.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +86 -6
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +84 -8
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +30 -5
- package/dist/render-system.d.ts.map +1 -1
- package/dist/renderer-inspect.d.ts +29 -0
- package/dist/renderer-inspect.d.ts.map +1 -0
- package/dist/scene/render-scene.d.ts +36 -2
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/temporal/coverage.d.ts +42 -0
- package/dist/temporal/coverage.d.ts.map +1 -0
- package/dist/temporal/frame-coordinator.d.ts +99 -0
- package/dist/temporal/frame-coordinator.d.ts.map +1 -0
- package/dist/temporal/frame.d.ts +44 -0
- package/dist/temporal/frame.d.ts.map +1 -0
- package/dist/temporal/gpu.d.ts +39 -0
- package/dist/temporal/gpu.d.ts.map +1 -0
- package/dist/temporal/history.d.ts +37 -0
- package/dist/temporal/history.d.ts.map +1 -0
- package/dist/temporal/index.d.ts +7 -0
- package/dist/temporal/index.d.ts.map +1 -0
- package/dist/temporal/index.mjs +8 -0
- package/dist/temporal/index.mjs.map +1 -0
- package/dist/temporal/inspection.d.ts +36 -0
- package/dist/temporal/inspection.d.ts.map +1 -0
- package/dist/temporal/scene-data-catalog.d.ts +48 -0
- package/dist/temporal/scene-data-catalog.d.ts.map +1 -0
- package/dist/temporal/scene-data.d.ts +43 -0
- package/dist/temporal/scene-data.d.ts.map +1 -0
- package/dist/temporal/standard-scene-data.d.ts +61 -0
- package/dist/temporal/standard-scene-data.d.ts.map +1 -0
- package/dist/temporal/taa-history-resources.d.ts +22 -0
- package/dist/temporal/taa-history-resources.d.ts.map +1 -0
- package/dist/temporal/taa-history-store.d.ts +27 -0
- package/dist/temporal/taa-history-store.d.ts.map +1 -0
- package/dist/temporal/taa-resolve.d.ts +15 -0
- package/dist/temporal/taa-resolve.d.ts.map +1 -0
- package/dist/temporal/temporal-view.d.ts +40 -0
- package/dist/temporal/temporal-view.d.ts.map +1 -0
- package/dist/temporal/transaction.d.ts +9 -0
- package/dist/temporal/transaction.d.ts.map +1 -0
- package/dist/temporal/view.d.ts +56 -0
- package/dist/temporal/view.d.ts.map +1 -0
- package/dist/transmission/backdrop.d.ts +147 -0
- package/dist/transmission/backdrop.d.ts.map +1 -0
- package/dist/transmission/inspection.d.ts +57 -0
- package/dist/transmission/inspection.d.ts.map +1 -0
- package/dist/transmission/oracle.d.ts +42 -0
- package/dist/transmission/oracle.d.ts.map +1 -0
- package/dist/transmission/projection.d.ts +37 -0
- package/dist/transmission/projection.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +30 -2
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-atlas.d.ts +10 -0
- package/dist/typed-shadow-atlas.d.ts.map +1 -0
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/capability.d.ts +57 -0
- package/dist/volume/capability.d.ts.map +1 -0
- package/dist/volume/component.d.ts +61 -0
- package/dist/volume/component.d.ts.map +1 -0
- package/dist/volume/extract.d.ts +11 -0
- package/dist/volume/extract.d.ts.map +1 -0
- package/dist/volume/inspection.d.ts +38 -0
- package/dist/volume/inspection.d.ts.map +1 -0
- package/dist/volume/passes.d.ts +38 -0
- package/dist/volume/passes.d.ts.map +1 -0
- package/dist/volume/recovery.d.ts +38 -0
- package/dist/volume/recovery.d.ts.map +1 -0
- package/dist/volume/resources.d.ts +57 -0
- package/dist/volume/resources.d.ts.map +1 -0
- package/dist/volume/temporal.d.ts +35 -0
- package/dist/volume/temporal.d.ts.map +1 -0
- package/package.json +24 -19
- package/src/__tests__/ai-user-cold-start.integration.test.ts +59 -0
- package/src/__tests__/ai-user-public-surface.test-d.ts +45 -0
- package/src/__tests__/bloom-exact-zero.unit.test.ts +202 -0
- package/src/__tests__/bloom-lifecycle.integration.test.ts +125 -0
- package/src/__tests__/construct-renderer-identity.unit.test.ts +4 -3
- package/src/__tests__/detached-inspection.integration.test.ts +177 -0
- package/src/__tests__/environment-fog-lanes.integration.test.ts +219 -0
- package/src/__tests__/environment-generation.integration.test.ts +141 -0
- package/src/__tests__/environment-selection.unit.test.ts +245 -0
- package/src/__tests__/factory-contract.integration.test.ts +1380 -9
- package/src/__tests__/frame-plan-contract.unit.test.ts +90 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +7 -0
- package/src/__tests__/gpu-driven-production.integration.test.ts +74 -22
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +37 -0
- package/src/__tests__/gpu-scene.unit.test.ts +10 -0
- package/src/__tests__/injection-kind-owner.test-d.ts +2 -1
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -14
- package/src/__tests__/material-contract-inventory.unit.test.ts +62 -0
- package/src/__tests__/material-cooked-projection.unit.test.ts +18 -146
- package/src/__tests__/materials-transmission-validation.unit.test.ts +36 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
- package/src/__tests__/morph-feature-plan.unit.test.ts +7 -0
- package/src/__tests__/motion-blur.pixel.integration.test.ts +121 -0
- package/src/__tests__/public-surface.test-d.ts +15 -1
- package/src/__tests__/render-error-code-owner.test-d.ts +14 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +11 -2
- package/src/__tests__/render-error-exhaustive.test-d.ts +3 -0
- package/src/__tests__/render-feature-errors.unit.test.ts +33 -3
- package/src/__tests__/render-feature-gpu-work.integration.test.ts +44 -0
- package/src/__tests__/render-feature-plan.test-d.ts +22 -89
- package/src/__tests__/render-scene-projection.unit.test.ts +28 -0
- package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +26 -0
- package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +21 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +423 -1
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +405 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +22 -0
- package/src/__tests__/scene-data-catalog.unit.test.ts +59 -0
- package/src/__tests__/scene-data-consumer.integration.test.ts +67 -0
- package/src/__tests__/scene-data-contract.test-d.ts +35 -0
- package/src/__tests__/scene-data-inspection.unit.test.ts +41 -0
- package/src/__tests__/scene-data-public-surface.test-d.ts +34 -0
- package/src/__tests__/shader-manifest-fixture.ts +111 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +123 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +24 -3
- package/src/__tests__/standard-pipeline.dawn.test.ts +15 -0
- package/src/__tests__/standard-pipeline.integration.test.ts +543 -1
- package/src/__tests__/standard-profile-oracle.unit.test.ts +12 -2
- package/src/__tests__/standard-temporal-producer.integration.test.ts +35 -0
- package/src/__tests__/surface-configuration.unit.test.ts +211 -12
- package/src/__tests__/taa-transaction.integration.test.ts +30 -0
- package/src/__tests__/temporal-admission.integration.test.ts +40 -0
- package/src/__tests__/temporal-coverage.unit.test.ts +35 -0
- package/src/__tests__/temporal-demand.unit.test.ts +44 -0
- package/src/__tests__/temporal-frame-coordinator.unit.test.ts +64 -0
- package/src/__tests__/temporal-graph-topology.unit.test.ts +51 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +170 -0
- package/src/__tests__/temporal-performance.integration.test.ts +615 -0
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +97 -0
- package/src/__tests__/temporal-transaction.integration.test.ts +60 -0
- package/src/__tests__/temporal-view.unit.test.ts +152 -0
- package/src/__tests__/transmission-prewarm.unit.test.ts +93 -0
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +230 -1
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +25 -1
- package/src/__tests__/urp-pipeline.unit.test.ts +4 -3
- package/src/__tests__/visibility-extract.integration.test.ts +27 -1
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +10 -0
- package/src/__tests__/volume-optics-oracle.unit.test.ts +85 -0
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +655 -0
- package/src/__tests__/volumetric-fog-component.unit.test.ts +71 -0
- package/src/__tests__/volumetric-fog-composite-stage-readback.dawn.test.ts +376 -0
- package/src/__tests__/volumetric-fog-errors.unit.test.ts +51 -0
- package/src/__tests__/volumetric-fog-inspection.unit.test.ts +77 -0
- package/src/__tests__/volumetric-fog-light-capability.unit.test.ts +19 -0
- package/src/__tests__/volumetric-fog-light-consumers.integration.test.ts +18 -0
- package/src/__tests__/volumetric-fog-light-errors.unit.test.ts +17 -0
- package/src/__tests__/volumetric-fog-light-topology.unit.test.ts +21 -0
- package/src/__tests__/volumetric-fog-light-transaction.integration.test.ts +53 -0
- package/src/__tests__/volumetric-fog-m9-watcher.integration.test.ts +27 -0
- package/src/__tests__/volumetric-fog-point-light-owner.integration.test.ts +44 -0
- package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +49 -0
- package/src/__tests__/volumetric-fog-point-spot-contract.unit.test.ts +28 -0
- package/src/__tests__/volumetric-fog-point-spot-lkg.integration.test.ts +65 -0
- package/src/__tests__/volumetric-fog-point-spot-selection.integration.test.ts +49 -0
- package/src/__tests__/volumetric-fog-point-spot-temporal.unit.test.ts +55 -0
- package/src/__tests__/volumetric-fog-projector-contract.unit.test.ts +22 -0
- package/src/__tests__/volumetric-fog-projector-inspection.unit.test.ts +12 -0
- package/src/__tests__/volumetric-fog-projector-surface-volume.integration.test.ts +11 -0
- package/src/__tests__/volumetric-fog-projector-transaction.integration.test.ts +26 -0
- package/src/__tests__/volumetric-fog-recovery.integration.test.ts +47 -0
- package/src/__tests__/volumetric-fog-selected-light-resolution.integration.test.ts +63 -0
- package/src/__tests__/volumetric-fog-spot-closure.integration.test.ts +26 -0
- package/src/__tests__/volumetric-fog-spot-contract.test-d.ts +21 -0
- package/src/__tests__/volumetric-fog-spot-contract.unit.test.ts +27 -0
- package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +14 -0
- package/src/__tests__/volumetric-fog-spot-optics.integration.test.ts +29 -0
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +550 -0
- package/src/__tests__/volumetric-fog-temporal-selected-light.unit.test.ts +33 -0
- package/src/__tests__/volumetric-fog-temporal.unit.test.ts +45 -0
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +237 -0
- package/src/__tests__/volumetric-fog-transparent.integration.test.ts +27 -0
- package/src/assembly/backend-contract.ts +47 -1
- package/src/assembly/factory.ts +1480 -505
- package/src/assembly/host-contract.ts +4 -0
- package/src/assembly/renderer-frame-transaction.ts +75 -0
- package/src/assembly/renderer-inspection.ts +112 -0
- package/src/assembly/renderer-lifecycle.ts +6 -0
- package/src/components/__tests__/motion-blur.unit.test.ts +14 -0
- package/src/components/__tests__/schema-contract.unit.test.ts +6 -1
- package/src/components/atmosphere.ts +10 -0
- package/src/components/camera.ts +2 -1
- package/src/components/fog.ts +9 -0
- package/src/components/index.ts +3 -0
- package/src/components/light-helpers.ts +4 -0
- package/src/components/motion-blur.ts +8 -0
- package/src/components/spot-light.ts +22 -3
- package/src/construct-renderer.ts +40 -3
- package/src/device/device-scope.ts +15 -1
- package/src/device/gpu-residency.ts +168 -58
- package/src/environment/frame.ts +185 -0
- package/src/environment/generation.ts +23 -0
- package/src/environment/graph.ts +9 -0
- package/src/environment/inspection.ts +87 -0
- package/src/environment/lifecycle.ts +250 -0
- package/src/environment/signature.ts +55 -0
- package/src/errors/render.ts +404 -1
- package/src/extract/camera.ts +78 -0
- package/src/extract/environment.ts +171 -0
- package/src/extract/visibility.ts +38 -19
- package/src/features/host.ts +36 -5
- package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +67 -0
- package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +53 -0
- package/src/features/motion-blur/motion-blur-feature.ts +119 -0
- package/src/features/motion-blur/motion-blur-params.ts +89 -0
- package/src/features/plan.ts +32 -3
- package/src/features/prepared-gpu-work.ts +21 -6
- package/src/features/prepared-graphics.ts +2 -1
- package/src/features/render-graph-raster.ts +2 -1
- package/src/features/targets.ts +24 -2
- package/src/features/types.ts +13 -0
- package/src/fullscreen-post-process-pass.ts +34 -4
- package/src/gpu-scene.ts +24 -0
- package/src/gpu-usage.ts +2 -0
- package/src/ibl/skylight-bind-group.ts +30 -38
- package/src/index.ts +104 -7
- package/src/inspection-types.ts +48 -0
- package/src/internal.ts +5 -0
- package/src/light-buffer-layout.ts +59 -26
- package/src/materials.ts +119 -24
- package/src/pbr-pipeline.ts +91 -29
- package/src/pipeline/standard-forward-lane.ts +178 -101
- package/src/pipeline/standard-pipeline.ts +176 -105
- package/src/pipeline/standard-post.ts +373 -0
- package/src/pipeline/standard-profile.ts +26 -3
- package/src/pipeline-builder.ts +102 -12
- package/src/pipeline-spec.ts +9 -0
- package/src/plugin.ts +2 -0
- package/src/record/__tests__/fullscreen-temporal-routing.unit.test.ts +25 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +47 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +12 -1
- package/src/record/__tests__/material-pipeline-pending-cache.unit.test.ts +22 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +75 -0
- package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +67 -0
- package/src/record/__tests__/temporal-payload.unit.test.ts +164 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +127 -0
- package/src/record/frame-lighting.ts +103 -89
- package/src/record/frame-snapshot.ts +170 -6
- package/src/record/frame-targets.ts +21 -8
- package/src/record/frame.ts +1014 -7
- package/src/record/gpu-timing.ts +224 -0
- package/src/record/main-pass-geometry.ts +86 -40
- package/src/record/main-pass-material.ts +120 -68
- package/src/record/main-pass-sprite-draws.ts +78 -101
- package/src/record/main-pass.ts +77 -4
- package/src/record/mesh-ssbo.ts +22 -3
- package/src/record/render-context.ts +194 -23
- package/src/record/shadow-pass.ts +197 -58
- package/src/record/skybox-post-pass.ts +97 -41
- package/src/record/typed-frame-graph.ts +704 -30
- package/src/record/view-ubo.ts +52 -4
- package/src/render-contract.ts +181 -6
- package/src/render-data.ts +50 -22
- package/src/render-graph-primitives.ts +18 -1
- package/src/render-pipeline.ts +144 -27
- package/src/render-system-extract.ts +522 -72
- package/src/render-system.ts +561 -41
- package/src/renderer-inspect.ts +66 -0
- package/src/scene/render-scene.ts +252 -7
- package/src/temporal/__tests__/taa-history-resources.unit.test.ts +45 -0
- package/src/temporal/coverage.ts +76 -0
- package/src/temporal/frame-coordinator.ts +311 -0
- package/src/temporal/frame.ts +128 -0
- package/src/temporal/gpu.ts +287 -0
- package/src/temporal/history.ts +92 -0
- package/src/temporal/index.ts +6 -0
- package/src/temporal/inspection.ts +97 -0
- package/src/temporal/scene-data-catalog.ts +200 -0
- package/src/temporal/scene-data.ts +149 -0
- package/src/temporal/standard-scene-data.ts +182 -0
- package/src/temporal/taa-history-resources.ts +128 -0
- package/src/temporal/taa-history-store.ts +79 -0
- package/src/temporal/taa-resolve.ts +34 -0
- package/src/temporal/temporal-view.ts +169 -0
- package/src/temporal/transaction.ts +17 -0
- package/src/temporal/view.ts +161 -0
- package/src/transmission/__tests__/capability.unit.test.ts +83 -0
- package/src/transmission/__tests__/composition.integration.test.ts +161 -0
- package/src/transmission/__tests__/inspection.unit.test.ts +241 -0
- package/src/transmission/__tests__/lifecycle.integration.test.ts +96 -0
- package/src/transmission/__tests__/oracle.unit.test.ts +131 -0
- package/src/transmission/__tests__/projection.unit.test.ts +71 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +437 -0
- package/src/transmission/__tests__/transmission-backdrop-topology.unit.test.ts +109 -0
- package/src/transmission/__tests__/transmission-backdrop.dawn.test.ts +105 -0
- package/src/transmission/backdrop.ts +572 -0
- package/src/transmission/inspection.ts +190 -0
- package/src/transmission/oracle.ts +141 -0
- package/src/transmission/projection.ts +83 -0
- package/src/typed-render-graph-primitives.ts +194 -11
- package/src/typed-shadow-atlas.ts +17 -0
- package/src/typed-shadow-passes.ts +6 -5
- package/src/volume/capability.ts +173 -0
- package/src/volume/component.ts +110 -0
- package/src/volume/extract.ts +21 -0
- package/src/volume/inspection.ts +78 -0
- package/src/volume/passes.ts +680 -0
- package/src/volume/recovery.ts +86 -0
- package/src/volume/resources.ts +236 -0
- package/src/volume/temporal.ts +89 -0
- package/dist/__tests__/authoring-path.unit.test.d.ts +0 -2
- package/dist/__tests__/authoring-path.unit.test.d.ts.map +0 -1
- package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts +0 -2
- package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts.map +0 -1
- package/dist/__tests__/callback-inference.test-d.d.ts +0 -2
- package/dist/__tests__/callback-inference.test-d.d.ts.map +0 -1
- package/dist/__tests__/cluster-binner.test.d.ts +0 -2
- package/dist/__tests__/cluster-binner.test.d.ts.map +0 -1
- package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/construct-renderer-identity.unit.test.d.ts +0 -2
- package/dist/__tests__/construct-renderer-identity.unit.test.d.ts.map +0 -1
- package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +0 -2
- package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +0 -1
- package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +0 -2
- package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +0 -1
- package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts +0 -2
- package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts.map +0 -1
- package/dist/__tests__/direct-light-snapshot.unit.test.d.ts +0 -2
- package/dist/__tests__/direct-light-snapshot.unit.test.d.ts.map +0 -1
- package/dist/__tests__/factory-contract.integration.test.d.ts +0 -2
- package/dist/__tests__/factory-contract.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/frame-observation.contract.test.d.ts +0 -2
- package/dist/__tests__/frame-observation.contract.test.d.ts.map +0 -1
- package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +0 -2
- package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +0 -1
- package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts +0 -2
- package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts +0 -6
- package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts +0 -2
- package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts +0 -2
- package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-production.integration.test.d.ts +0 -2
- package/dist/__tests__/gpu-driven-production.integration.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts +0 -2
- package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +0 -18
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts +0 -2
- package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-view-reference.d.ts +0 -15
- package/dist/__tests__/gpu-driven-view-reference.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-view.browser.test.d.ts +0 -2
- package/dist/__tests__/gpu-driven-view.browser.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-view.dawn.test.d.ts +0 -2
- package/dist/__tests__/gpu-driven-view.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-driven-view.unit.test.d.ts +0 -2
- package/dist/__tests__/gpu-driven-view.unit.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts +0 -2
- package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts +0 -7
- package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +0 -1
- package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts +0 -2
- package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts +0 -2
- package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-scene-schema.unit.test.d.ts +0 -2
- package/dist/__tests__/gpu-scene-schema.unit.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-scene.dawn.test.d.ts +0 -2
- package/dist/__tests__/gpu-scene.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-scene.unit.test.d.ts +0 -2
- package/dist/__tests__/gpu-scene.unit.test.d.ts.map +0 -1
- package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +0 -2
- package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +0 -1
- package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts +0 -2
- package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts.map +0 -1
- package/dist/__tests__/injection-kind-owner.test-d.d.ts +0 -2
- package/dist/__tests__/injection-kind-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts +0 -2
- package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/light-buffer-layout.unit.test.d.ts +0 -2
- package/dist/__tests__/light-buffer-layout.unit.test.d.ts.map +0 -1
- package/dist/__tests__/material-contract-inventory.unit.test.d.ts +0 -2
- package/dist/__tests__/material-contract-inventory.unit.test.d.ts.map +0 -1
- package/dist/__tests__/material-cooked-projection.unit.test.d.ts +0 -2
- package/dist/__tests__/material-cooked-projection.unit.test.d.ts.map +0 -1
- package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts +0 -2
- package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts.map +0 -1
- package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts +0 -2
- package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts.map +0 -1
- package/dist/__tests__/material-stride-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/material-stride-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/mesh-material-bindings.unit.test.d.ts +0 -2
- package/dist/__tests__/mesh-material-bindings.unit.test.d.ts.map +0 -1
- package/dist/__tests__/mesh-stride-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/mesh-stride-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts +0 -2
- package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts +0 -2
- package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts.map +0 -1
- package/dist/__tests__/morph-feature-plan.unit.test.d.ts +0 -2
- package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +0 -1
- package/dist/__tests__/morph-visual-evidence.integration.test.d.ts +0 -2
- package/dist/__tests__/morph-visual-evidence.integration.test.d.ts.map +0 -1
- package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts +0 -2
- package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts +0 -2
- package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-store.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-store.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts.map +0 -1
- package/dist/__tests__/profiler-default-off.test.d.ts +0 -2
- package/dist/__tests__/profiler-default-off.test.d.ts.map +0 -1
- package/dist/__tests__/profiler-phase-catalog.test.d.ts +0 -2
- package/dist/__tests__/profiler-phase-catalog.test.d.ts.map +0 -1
- package/dist/__tests__/profiler-phase-integration.test.d.ts +0 -2
- package/dist/__tests__/profiler-phase-integration.test.d.ts.map +0 -1
- package/dist/__tests__/profiler-phase-token.test.d.ts +0 -2
- package/dist/__tests__/profiler-phase-token.test.d.ts.map +0 -1
- package/dist/__tests__/public-surface.test-d.d.ts +0 -2
- package/dist/__tests__/public-surface.test-d.d.ts.map +0 -1
- package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts +0 -2
- package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-error-code-owner.test-d.d.ts +0 -2
- package/dist/__tests__/render-error-code-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-error-detail-ssot.test-d.d.ts +0 -2
- package/dist/__tests__/render-error-detail-ssot.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts +0 -2
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-assembly.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-assembly.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-context.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-context.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-contract.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-contract.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-docs.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-docs.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-errors.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-errors.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts +0 -2
- package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-plan.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-plan.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-plan.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-public-surface.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-public-surface.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-retry.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-retry.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-scheduling.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-scheduling.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-visibility-context.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-visibility-context.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-zero-work.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-zero-work.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-graph-compute-raster-gpu.d.ts +0 -7
- package/dist/__tests__/render-graph-compute-raster-gpu.d.ts.map +0 -1
- package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts +0 -2
- package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts.map +0 -1
- package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts +0 -2
- package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/render-graph-hzb-gpu.d.ts +0 -7
- package/dist/__tests__/render-graph-hzb-gpu.d.ts.map +0 -1
- package/dist/__tests__/render-graph-hzb.browser.test.d.ts +0 -2
- package/dist/__tests__/render-graph-hzb.browser.test.d.ts.map +0 -1
- package/dist/__tests__/render-graph-hzb.dawn.test.d.ts +0 -2
- package/dist/__tests__/render-graph-hzb.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/render-graph-primitives.unit.test.d.ts +0 -2
- package/dist/__tests__/render-graph-primitives.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts +0 -12
- package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts.map +0 -1
- package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts +0 -2
- package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts.map +0 -1
- package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts +0 -2
- package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/render-scene-projection.unit.test.d.ts +0 -2
- package/dist/__tests__/render-scene-projection.unit.test.d.ts.map +0 -1
- package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts +0 -2
- package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts.map +0 -1
- package/dist/__tests__/renderer-lifecycle.integration.test.d.ts +0 -2
- package/dist/__tests__/renderer-lifecycle.integration.test.d.ts.map +0 -1
- package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts +0 -2
- package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts.map +0 -1
- package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts +0 -2
- package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts.map +0 -1
- package/dist/__tests__/shader-stage-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/shader-stage-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/ssao-config.unit.test.d.ts +0 -2
- package/dist/__tests__/ssao-config.unit.test.d.ts.map +0 -1
- package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +0 -2
- package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +0 -1
- package/dist/__tests__/standard-descriptors.test-d.d.ts +0 -2
- package/dist/__tests__/standard-descriptors.test-d.d.ts.map +0 -1
- package/dist/__tests__/standard-pipeline.dawn.test.d.ts +0 -2
- package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +0 -1
- package/dist/__tests__/standard-pipeline.integration.test.d.ts +0 -2
- package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +0 -1
- package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +0 -2
- package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +0 -1
- package/dist/__tests__/surface-configuration.unit.test.d.ts +0 -2
- package/dist/__tests__/surface-configuration.unit.test.d.ts.map +0 -1
- package/dist/__tests__/texture-usage-surface.unit.test.d.ts +0 -2
- package/dist/__tests__/texture-usage-surface.unit.test.d.ts.map +0 -1
- package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts +0 -2
- package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts.map +0 -1
- package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts +0 -2
- package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts.map +0 -1
- package/dist/__tests__/urp-pipeline.unit.test.d.ts +0 -2
- package/dist/__tests__/urp-pipeline.unit.test.d.ts.map +0 -1
- package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts +0 -2
- package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts.map +0 -1
- package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts +0 -2
- package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-diagnostics.integration.test.d.ts +0 -2
- package/dist/__tests__/visibility-diagnostics.integration.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-extract.integration.test.d.ts +0 -2
- package/dist/__tests__/visibility-extract.integration.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-extract.perf.test.d.ts +0 -2
- package/dist/__tests__/visibility-extract.perf.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts +0 -2
- package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-hidden-report.unit.test.d.ts +0 -2
- package/dist/__tests__/visibility-hidden-report.unit.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-instances.integration.test.d.ts +0 -2
- package/dist/__tests__/visibility-instances.integration.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-multi-world.integration.test.d.ts +0 -2
- package/dist/__tests__/visibility-multi-world.integration.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts +0 -2
- package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts +0 -2
- package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-public-surface.test-d.d.ts +0 -2
- package/dist/__tests__/visibility-public-surface.test-d.d.ts.map +0 -1
- package/dist/__tests__/visibility-resolver.unit.test.d.ts +0 -2
- package/dist/__tests__/visibility-resolver.unit.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +0 -2
- package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +0 -1
- package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts +0 -2
- package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts.map +0 -1
- package/dist/__tests__/vocabulary.unit.test.d.ts +0 -2
- package/dist/__tests__/vocabulary.unit.test.d.ts.map +0 -1
- package/dist/chunk-CQXZC5XI.mjs.map +0 -1
- package/dist/chunk-HCOGPHKS.mjs +0 -93
- package/dist/chunk-HCOGPHKS.mjs.map +0 -1
- package/dist/chunk-YEJIUW7D.mjs.map +0 -1
- package/dist/components/__tests__/points-lines-admission.unit.test.d.ts +0 -2
- package/dist/components/__tests__/points-lines-admission.unit.test.d.ts.map +0 -1
- package/dist/components/__tests__/points-lines-schema.unit.test.d.ts +0 -2
- package/dist/components/__tests__/points-lines-schema.unit.test.d.ts.map +0 -1
- package/dist/components/__tests__/schema-contract.unit.test.d.ts +0 -2
- package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +0 -1
- package/dist/components/__tests__/schema-parity.unit.test.d.ts +0 -2
- package/dist/components/__tests__/schema-parity.unit.test.d.ts.map +0 -1
- package/dist/components/__tests__/visibility-schema.unit.test.d.ts +0 -2
- package/dist/components/__tests__/visibility-schema.unit.test.d.ts.map +0 -1
- package/dist/points-lines/__tests__/bounds.unit.test.d.ts +0 -2
- package/dist/points-lines/__tests__/bounds.unit.test.d.ts.map +0 -1
- package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts +0 -2
- package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts.map +0 -1
- package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts +0 -2
- package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts.map +0 -1
- package/dist/points-lines/__tests__/inspection.unit.test.d.ts +0 -2
- package/dist/points-lines/__tests__/inspection.unit.test.d.ts.map +0 -1
- package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts +0 -2
- package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts.map +0 -1
- package/dist/points-lines/__tests__/points-lines.bench.d.ts +0 -2
- package/dist/points-lines/__tests__/points-lines.bench.d.ts.map +0 -1
- package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts +0 -2
- package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts.map +0 -1
- package/dist/points-lines/__tests__/snapshot.unit.test.d.ts +0 -2
- package/dist/points-lines/__tests__/snapshot.unit.test.d.ts.map +0 -1
- package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts +0 -2
- package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/material-bg-cache.unit.test.d.ts +0 -2
- package/dist/record/__tests__/material-bg-cache.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/material-slot-plan.unit.test.d.ts +0 -2
- package/dist/record/__tests__/material-slot-plan.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +0 -2
- package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/video-texture-view.unit.test.d.ts +0 -2
- package/dist/record/__tests__/video-texture-view.unit.test.d.ts.map +0 -1
package/src/record/frame.ts
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
import { HANDLE_NINESLICE_QUAD, resolveAssetHandle } from '@forgeax/engine-assets-runtime';
|
|
5
5
|
import type { World } from '@forgeax/engine-ecs';
|
|
6
6
|
import type { RenderReadLease } from '@forgeax/engine-ecs/projection';
|
|
7
|
+
import { mat4, vec3 } from '@forgeax/engine-math';
|
|
7
8
|
import {
|
|
8
9
|
type CurrentFrameObservationLease,
|
|
9
10
|
createCurrentFrameObservationLease,
|
|
10
11
|
} from '@forgeax/engine-render-graph';
|
|
11
12
|
import {
|
|
13
|
+
type Buffer,
|
|
12
14
|
err,
|
|
13
15
|
ok,
|
|
14
16
|
type Result,
|
|
@@ -21,14 +23,25 @@ import type { MaterialRenderState, MeshAsset } from '@forgeax/engine-types';
|
|
|
21
23
|
import { handleSlot, toShared } from '@forgeax/engine-types';
|
|
22
24
|
import type { MeshGpuHandles } from '../device/gpu-residency';
|
|
23
25
|
import { ObservationUnavailableError, type ObservationUnavailableReason } from '../errors/render';
|
|
26
|
+
import type { FogFrame } from '../extract/environment';
|
|
24
27
|
import type { GpuDrivenProduction, PreparedGpuDrivenFrame } from '../gpu-driven/production-raster';
|
|
25
28
|
import { GpuBuffer } from '../gpu-resource';
|
|
26
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
GPU_BUFFER_USAGE_COPY_DST,
|
|
31
|
+
GPU_BUFFER_USAGE_UNIFORM,
|
|
32
|
+
GPU_BUFFER_USAGE_VERTEX,
|
|
33
|
+
} from '../gpu-usage';
|
|
27
34
|
import { disposeTransientInstanceBuffers } from '../instance-buffer-cache';
|
|
28
|
-
import type {
|
|
35
|
+
import type {
|
|
36
|
+
CameraSnapshot,
|
|
37
|
+
RenderRecordPhase,
|
|
38
|
+
SpotLightProjectorFrameContext,
|
|
39
|
+
VolumetricFogFrameContext,
|
|
40
|
+
} from '../render-contract';
|
|
29
41
|
import type {
|
|
30
42
|
DispatchEntry,
|
|
31
43
|
ExtractedLights,
|
|
44
|
+
ExtractedVolumetricFog,
|
|
32
45
|
MaterialSnapshot,
|
|
33
46
|
RenderableSnapshot,
|
|
34
47
|
SkyboxSnapshot,
|
|
@@ -40,6 +53,10 @@ import {
|
|
|
40
53
|
TRANSPARENT_SORT_MODE_LAYER_Y,
|
|
41
54
|
TRANSPARENT_SORT_MODE_LAYER_Z,
|
|
42
55
|
} from '../systems/transparent-sort-config';
|
|
56
|
+
import type { TransmissionDemand } from '../transmission/projection';
|
|
57
|
+
import { hasVolumetricFogCapability } from '../volume/capability';
|
|
58
|
+
import { inspectVolumetricFogResources, VOLUMETRIC_FOG_PARAMS_BYTES } from '../volume/resources';
|
|
59
|
+
import { resolveVolumeTemporalReset, type VolumeTemporalSignature } from '../volume/temporal';
|
|
43
60
|
import {
|
|
44
61
|
buildPerFrameBindGroups,
|
|
45
62
|
prepareFrameLighting,
|
|
@@ -184,13 +201,17 @@ export async function observeCurrentFrame(
|
|
|
184
201
|
});
|
|
185
202
|
}
|
|
186
203
|
|
|
204
|
+
import { createTemporalView, resolveTemporalReset } from '../temporal/view';
|
|
205
|
+
import { inspectVolumetricFog } from '../volume/inspection';
|
|
187
206
|
import {
|
|
188
207
|
acquireSwapChainTarget,
|
|
189
208
|
graphExecutionPhase,
|
|
190
209
|
resolveShadowMapSize,
|
|
191
210
|
resolveSpotShadowMapSize,
|
|
192
211
|
} from './frame-targets';
|
|
212
|
+
import type { GpuTimingCapture } from './gpu-timing';
|
|
193
213
|
import {
|
|
214
|
+
computeProjectionMatrix,
|
|
194
215
|
computeViewMatrix,
|
|
195
216
|
driveLazyEquirectProjection,
|
|
196
217
|
selectLazyEquirectHandle,
|
|
@@ -205,6 +226,7 @@ import {
|
|
|
205
226
|
ensureCompiledFrameGraph,
|
|
206
227
|
executeCompiledFrameGraph,
|
|
207
228
|
type RenderFeatureGraphCandidate,
|
|
229
|
+
settleVolumetricFogGraphCandidate,
|
|
208
230
|
} from './typed-frame-graph';
|
|
209
231
|
import { writePointsLinesViewUbo, writeViewUbo } from './view-ubo';
|
|
210
232
|
|
|
@@ -289,6 +311,703 @@ function runRecordProfilePhase<T>(
|
|
|
289
311
|
return runner === undefined ? action() : runner(phase, action);
|
|
290
312
|
}
|
|
291
313
|
|
|
314
|
+
const VOLUMETRIC_FOG_PASS_COUNT = 4;
|
|
315
|
+
|
|
316
|
+
type VolumetricFogParamsSlot = 0 | 1;
|
|
317
|
+
|
|
318
|
+
function nextVolumetricFogParamsSlot(frameState: RenderFrameState): VolumetricFogParamsSlot {
|
|
319
|
+
const accepted = frameState.volumetricFogParamsAcceptedSlot;
|
|
320
|
+
const pending = frameState.volumetricFogParamsPendingSlot;
|
|
321
|
+
if (pending !== null && pending !== accepted) return pending;
|
|
322
|
+
return accepted === null ? 0 : accepted === 0 ? 1 : 0;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function stageVolumetricFogParams(
|
|
326
|
+
internals: RenderSystemInternals,
|
|
327
|
+
frameState: RenderFrameState,
|
|
328
|
+
params: Float32Array,
|
|
329
|
+
): Buffer | undefined {
|
|
330
|
+
const slot = nextVolumetricFogParamsSlot(frameState);
|
|
331
|
+
let buffer = frameState.volumetricFogParamsBuffers[slot];
|
|
332
|
+
if (buffer === null) {
|
|
333
|
+
const created = internals.device.createBuffer({
|
|
334
|
+
label: `volumetric-fog-params-${slot}`,
|
|
335
|
+
size: VOLUMETRIC_FOG_PARAMS_BYTES,
|
|
336
|
+
usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
|
|
337
|
+
mappedAtCreation: false,
|
|
338
|
+
});
|
|
339
|
+
if (!created.ok) {
|
|
340
|
+
internals.errorRegistry.fire(created.error);
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
343
|
+
buffer = created.value;
|
|
344
|
+
frameState.volumetricFogParamsBuffers[slot] = buffer;
|
|
345
|
+
}
|
|
346
|
+
const written = internals.device.queue.writeBuffer(buffer, 0, params);
|
|
347
|
+
if (!written.ok) {
|
|
348
|
+
internals.errorRegistry.fire(written.error);
|
|
349
|
+
return undefined;
|
|
350
|
+
}
|
|
351
|
+
frameState.volumetricFogParamsPendingSlot = slot;
|
|
352
|
+
frameState.volumetricFogPendingParams = new Float32Array(params);
|
|
353
|
+
return buffer;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** Retire parameter buffers only after the submit that stopped using them. */
|
|
357
|
+
function retireVolumetricFogParams(
|
|
358
|
+
internals: RenderSystemInternals,
|
|
359
|
+
frameState: RenderFrameState,
|
|
360
|
+
): void {
|
|
361
|
+
const buffers = frameState.volumetricFogParamsBuffers;
|
|
362
|
+
frameState.volumetricFogParamsBuffers = [null, null];
|
|
363
|
+
frameState.volumetricFogParamsPendingSlot = null;
|
|
364
|
+
frameState.volumetricFogParamsAcceptedSlot = null;
|
|
365
|
+
frameState.volumetricFogAcceptedParams = undefined;
|
|
366
|
+
frameState.volumetricFogPendingParams = undefined;
|
|
367
|
+
const live = buffers.filter((buffer): buffer is Buffer => buffer !== null);
|
|
368
|
+
if (live.length === 0) return;
|
|
369
|
+
const device = internals.device;
|
|
370
|
+
const release = (): void => {
|
|
371
|
+
for (const buffer of live) {
|
|
372
|
+
const destroyed = device.destroyBuffer(buffer);
|
|
373
|
+
if (!destroyed.ok) internals.errorRegistry.fire(destroyed.error);
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
try {
|
|
377
|
+
void device.queue.onSubmittedWorkDone().then(release, release);
|
|
378
|
+
} catch {
|
|
379
|
+
release();
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function volumeRevision(values: readonly number[]): number {
|
|
384
|
+
let hash = 2166136261;
|
|
385
|
+
for (const value of values) {
|
|
386
|
+
const quantized = Number.isFinite(value) ? Math.round(value * 1_000_000) : 0;
|
|
387
|
+
hash = Math.imul(hash ^ quantized, 16777619) >>> 0;
|
|
388
|
+
}
|
|
389
|
+
return hash;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function volumeTemporalSignature(
|
|
393
|
+
fog: ExtractedVolumetricFog,
|
|
394
|
+
prepared: VolumetricFogFrameContext,
|
|
395
|
+
camera: CameraSnapshot,
|
|
396
|
+
lights: ExtractedLights,
|
|
397
|
+
width: number,
|
|
398
|
+
height: number,
|
|
399
|
+
): VolumeTemporalSignature {
|
|
400
|
+
const authored = fog.fog;
|
|
401
|
+
const directional = lights.directional;
|
|
402
|
+
const cameraRevision = volumeRevision([
|
|
403
|
+
...camera.world,
|
|
404
|
+
camera.fov,
|
|
405
|
+
camera.aspect,
|
|
406
|
+
camera.near,
|
|
407
|
+
camera.far,
|
|
408
|
+
camera.orthoLeft,
|
|
409
|
+
camera.orthoRight,
|
|
410
|
+
camera.orthoBottom,
|
|
411
|
+
camera.orthoTop,
|
|
412
|
+
]);
|
|
413
|
+
const fogRevision =
|
|
414
|
+
authored === undefined
|
|
415
|
+
? 0
|
|
416
|
+
: volumeRevision([
|
|
417
|
+
...authored.bounds.min,
|
|
418
|
+
...authored.bounds.max,
|
|
419
|
+
...authored.extinction,
|
|
420
|
+
...authored.albedo,
|
|
421
|
+
...authored.emission,
|
|
422
|
+
authored.anisotropy,
|
|
423
|
+
authored.maxDistance,
|
|
424
|
+
]);
|
|
425
|
+
const selectedSpot =
|
|
426
|
+
fog.spotLightEntity === undefined
|
|
427
|
+
? fog.lightKind === 'spot'
|
|
428
|
+
? lights.spot.find((spot) => spot.entity === fog.lightEntity)
|
|
429
|
+
: undefined
|
|
430
|
+
: lights.spot.find((spot) => spot.entity === fog.spotLightEntity);
|
|
431
|
+
const selectedPoint =
|
|
432
|
+
fog.pointLightEntity === undefined
|
|
433
|
+
? fog.lightKind === 'point'
|
|
434
|
+
? lights.point.find((point) => point.entity === fog.lightEntity)
|
|
435
|
+
: undefined
|
|
436
|
+
: lights.point.find((point) => point.entity === fog.pointLightEntity);
|
|
437
|
+
const selectedDirectional =
|
|
438
|
+
fog.lightKind === 'directional' && directional?.entity === fog.lightEntity
|
|
439
|
+
? directional
|
|
440
|
+
: undefined;
|
|
441
|
+
const lightRevision =
|
|
442
|
+
selectedSpot === undefined && selectedPoint === undefined && selectedDirectional === undefined
|
|
443
|
+
? 0
|
|
444
|
+
: volumeRevision(
|
|
445
|
+
selectedSpot === undefined && selectedPoint === undefined
|
|
446
|
+
? selectedDirectional === undefined
|
|
447
|
+
? []
|
|
448
|
+
: [
|
|
449
|
+
...selectedDirectional.direction,
|
|
450
|
+
...selectedDirectional.color,
|
|
451
|
+
selectedDirectional.intensity,
|
|
452
|
+
...(lights.lightViewProj?.flatMap((matrix) => [...matrix]) ?? []),
|
|
453
|
+
]
|
|
454
|
+
: [
|
|
455
|
+
...(selectedPoint === undefined
|
|
456
|
+
? []
|
|
457
|
+
: [
|
|
458
|
+
...selectedPoint.position,
|
|
459
|
+
...selectedPoint.color,
|
|
460
|
+
selectedPoint.intensity,
|
|
461
|
+
selectedPoint.invRangeSquared,
|
|
462
|
+
selectedPoint.shadowAtlasLayer ?? -1,
|
|
463
|
+
selectedPoint.shadowNear ?? 0,
|
|
464
|
+
selectedPoint.shadowFar ?? 0,
|
|
465
|
+
]),
|
|
466
|
+
...(selectedSpot === undefined
|
|
467
|
+
? []
|
|
468
|
+
: [
|
|
469
|
+
...selectedSpot.position,
|
|
470
|
+
...selectedSpot.direction,
|
|
471
|
+
...selectedSpot.color,
|
|
472
|
+
selectedSpot.intensity,
|
|
473
|
+
selectedSpot.invRangeSquared,
|
|
474
|
+
selectedSpot.cosInner,
|
|
475
|
+
selectedSpot.cosOuter,
|
|
476
|
+
selectedSpot.depthBias ?? 0.005,
|
|
477
|
+
selectedSpot.normalBias ?? 0.05,
|
|
478
|
+
selectedSpot.pcfKernelSize ?? 3,
|
|
479
|
+
selectedSpot.shadowAtlasTile,
|
|
480
|
+
...(selectedSpot.lightViewProj === undefined
|
|
481
|
+
? []
|
|
482
|
+
: [...selectedSpot.lightViewProj]),
|
|
483
|
+
]),
|
|
484
|
+
],
|
|
485
|
+
);
|
|
486
|
+
return {
|
|
487
|
+
cameraRevision,
|
|
488
|
+
fogRevision,
|
|
489
|
+
lightRevision,
|
|
490
|
+
densityGeneration: prepared.densityGeneration,
|
|
491
|
+
width,
|
|
492
|
+
height,
|
|
493
|
+
...(fog.lightKind === undefined ? {} : { lightKind: fog.lightKind }),
|
|
494
|
+
...(fog.lightEntity === undefined ? {} : { lightEntity: fog.lightEntity }),
|
|
495
|
+
...(fog.pointLightEntity === undefined ? {} : { pointLightEntity: fog.pointLightEntity }),
|
|
496
|
+
...(fog.spotLightEntity === undefined ? {} : { spotLightEntity: fog.spotLightEntity }),
|
|
497
|
+
...(fog.projector === undefined ? {} : { projector: fog.projector }),
|
|
498
|
+
lightShadowRevision: lightRevision,
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function resolveVolumetricFogHistoryContext(
|
|
503
|
+
frameState: RenderFrameState,
|
|
504
|
+
graph: import('@forgeax/engine-render-graph').CompiledRenderGraph<
|
|
505
|
+
import('../render-pipeline').RenderPipelineFrame
|
|
506
|
+
>,
|
|
507
|
+
fog: ExtractedVolumetricFog,
|
|
508
|
+
prepared: VolumetricFogFrameContext,
|
|
509
|
+
camera: CameraSnapshot,
|
|
510
|
+
lights: ExtractedLights,
|
|
511
|
+
width: number,
|
|
512
|
+
height: number,
|
|
513
|
+
): { readonly context: VolumetricFogFrameContext; readonly signature: VolumeTemporalSignature } {
|
|
514
|
+
const signature = volumeTemporalSignature(fog, prepared, camera, lights, width, height);
|
|
515
|
+
const acceptedGraph = frameState.volumetricFogHistoryGraph;
|
|
516
|
+
const acceptedSlot = frameState.volumetricFogHistorySlot;
|
|
517
|
+
const previousSignature = frameState.volumetricFogHistorySignature;
|
|
518
|
+
let reset = acceptedGraph !== graph || acceptedSlot === null || previousSignature === null;
|
|
519
|
+
if (!reset && previousSignature !== null) {
|
|
520
|
+
const temporal = frameState.temporalFrame;
|
|
521
|
+
const previousResetReason = temporal?.resetReason;
|
|
522
|
+
const reprojection =
|
|
523
|
+
previousResetReason === 'out-of-screen'
|
|
524
|
+
? 'out-of-screen'
|
|
525
|
+
: previousResetReason === 'depth-discontinuity'
|
|
526
|
+
? 'depth-discontinuity'
|
|
527
|
+
: undefined;
|
|
528
|
+
reset = resolveVolumeTemporalReset(previousSignature, signature, {
|
|
529
|
+
taaEnabled: camera.antialias === 'taa',
|
|
530
|
+
...(reprojection === undefined ? {} : { reprojection }),
|
|
531
|
+
}).reset;
|
|
532
|
+
}
|
|
533
|
+
const historyReadSlot = reset ? null : acceptedSlot;
|
|
534
|
+
const historyWriteSlot = reset || acceptedSlot === null ? 0 : acceptedSlot === 0 ? 1 : 0;
|
|
535
|
+
return {
|
|
536
|
+
context: {
|
|
537
|
+
...prepared,
|
|
538
|
+
historyReadSlot,
|
|
539
|
+
historyWriteSlot,
|
|
540
|
+
historyValid: historyReadSlot !== null,
|
|
541
|
+
},
|
|
542
|
+
signature,
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Resolve the authored density POD into the renderer-owned GPU resources used
|
|
548
|
+
* by the graph. This is deliberately a pull operation: a missing/stale
|
|
549
|
+
* handle or failed upload produces a structured error and leaves the graph
|
|
550
|
+
* candidate disabled for this frame rather than binding a synthetic density.
|
|
551
|
+
*/
|
|
552
|
+
function prepareVolumetricFogFrame(
|
|
553
|
+
internals: RenderSystemInternals,
|
|
554
|
+
frameState: RenderFrameState,
|
|
555
|
+
world: World,
|
|
556
|
+
worlds: readonly World[],
|
|
557
|
+
fog: ExtractedVolumetricFog | undefined,
|
|
558
|
+
lights: ExtractedLights,
|
|
559
|
+
volumeCapability: boolean,
|
|
560
|
+
projector: SpotLightProjectorFrameContext | undefined,
|
|
561
|
+
): VolumetricFogFrameContext | undefined {
|
|
562
|
+
if (
|
|
563
|
+
!volumeCapability ||
|
|
564
|
+
fog?.status !== 'available' ||
|
|
565
|
+
fog.fog === undefined ||
|
|
566
|
+
fog.densityHandle === undefined ||
|
|
567
|
+
fog.densityAsset === undefined ||
|
|
568
|
+
(fog.lightKind === 'spot'
|
|
569
|
+
? lights.spot.find((light) => light.entity === fog.lightEntity) === undefined
|
|
570
|
+
: fog.lightKind === 'point'
|
|
571
|
+
? lights.point.find((light) => light.entity === fog.lightEntity) === undefined
|
|
572
|
+
: lights.directional === undefined)
|
|
573
|
+
) {
|
|
574
|
+
return undefined;
|
|
575
|
+
}
|
|
576
|
+
const ownerWorld = worlds[fog.worldId ?? 0] ?? world;
|
|
577
|
+
const resident = internals.gpuStore.ensureResident(
|
|
578
|
+
fog.densityHandle,
|
|
579
|
+
fog.densityAsset,
|
|
580
|
+
ownerWorld,
|
|
581
|
+
);
|
|
582
|
+
if (!resident.ok || !('texture' in resident.value)) {
|
|
583
|
+
if (!resident.ok) {
|
|
584
|
+
internals.errorRegistry.fire(
|
|
585
|
+
resident.error instanceof RhiError
|
|
586
|
+
? resident.error
|
|
587
|
+
: new RhiError({
|
|
588
|
+
code: 'webgpu-runtime-error',
|
|
589
|
+
expected: 'volumetric density residency to resolve a GPU texture',
|
|
590
|
+
hint: 'repair the authored TextureAsset payload and retry the next frame',
|
|
591
|
+
detail: { error: resident.error },
|
|
592
|
+
}),
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
return undefined;
|
|
596
|
+
}
|
|
597
|
+
const params = new Float32Array(32);
|
|
598
|
+
params.set(fog.fog.bounds.min, 0);
|
|
599
|
+
params.set(fog.fog.bounds.max, 4);
|
|
600
|
+
params.set(fog.fog.extinction, 8);
|
|
601
|
+
params.set(fog.fog.albedo, 12);
|
|
602
|
+
params.set(fog.fog.emission, 16);
|
|
603
|
+
const selectedPoint =
|
|
604
|
+
fog.pointLightEntity === undefined
|
|
605
|
+
? undefined
|
|
606
|
+
: lights.point.find((light) => light.entity === fog.pointLightEntity);
|
|
607
|
+
const selectedSpot =
|
|
608
|
+
fog.spotLightEntity === undefined
|
|
609
|
+
? fog.lightKind === 'spot'
|
|
610
|
+
? lights.spot.find((light) => light.entity === fog.lightEntity)
|
|
611
|
+
: undefined
|
|
612
|
+
: lights.spot.find((light) => light.entity === fog.spotLightEntity);
|
|
613
|
+
const lightDirection =
|
|
614
|
+
selectedSpot?.direction ?? lights.directional?.direction ?? vec3.create(0, -1, 0);
|
|
615
|
+
const lightColor = selectedSpot?.color ?? lights.directional?.color ?? vec3.create(0, 0, 0);
|
|
616
|
+
if (lightDirection === undefined || lightColor === undefined) return undefined;
|
|
617
|
+
params.set(lightDirection, 20);
|
|
618
|
+
// Reuse the vec4 padding lane as the renderer-owned frame phase for
|
|
619
|
+
// sub-froxel jitter. The temporal resolver consumes it without growing the
|
|
620
|
+
// public fog component or allocating another uniform buffer.
|
|
621
|
+
params[23] = frameState.frameNumber % 1024;
|
|
622
|
+
const selectedSpotIndex =
|
|
623
|
+
selectedSpot === undefined
|
|
624
|
+
? -1
|
|
625
|
+
: lights.spot.findIndex((light) => light.entity === selectedSpot.entity);
|
|
626
|
+
params.set(lightColor, 24);
|
|
627
|
+
params[19] =
|
|
628
|
+
selectedPoint === undefined
|
|
629
|
+
? -1
|
|
630
|
+
: lights.point.findIndex((light) => light.entity === selectedPoint.entity);
|
|
631
|
+
params[27] = selectedSpotIndex;
|
|
632
|
+
params[28] = fog.fog.maxDistance;
|
|
633
|
+
params[29] = fog.fog.anisotropy;
|
|
634
|
+
params[30] =
|
|
635
|
+
selectedPoint !== undefined && selectedSpot !== undefined
|
|
636
|
+
? 3
|
|
637
|
+
: selectedPoint !== undefined
|
|
638
|
+
? 1
|
|
639
|
+
: selectedSpot !== undefined
|
|
640
|
+
? 2
|
|
641
|
+
: 0;
|
|
642
|
+
// The temporal shader reads this lane after the record stage resolves the
|
|
643
|
+
// accepted graph/slot. It is overwritten on the next queue-visible frame;
|
|
644
|
+
// the first candidate deliberately starts with history disabled.
|
|
645
|
+
params[31] =
|
|
646
|
+
frameState.temporalFrame !== undefined && frameState.temporalFrame.resetReason === 'none'
|
|
647
|
+
? 1
|
|
648
|
+
: 0;
|
|
649
|
+
|
|
650
|
+
const paramsBuffer = stageVolumetricFogParams(internals, frameState, params);
|
|
651
|
+
if (paramsBuffer === undefined) return undefined;
|
|
652
|
+
return {
|
|
653
|
+
densityTexture: resident.value.texture.handle,
|
|
654
|
+
densityView: resident.value.view,
|
|
655
|
+
paramsBuffer,
|
|
656
|
+
densityGeneration: resident.value.receipt.generation,
|
|
657
|
+
historyReadSlot: null,
|
|
658
|
+
historyWriteSlot: 0,
|
|
659
|
+
historyValid: false,
|
|
660
|
+
...(projector === undefined
|
|
661
|
+
? {}
|
|
662
|
+
: {
|
|
663
|
+
projectorTexture: projector.texture,
|
|
664
|
+
projectorView: projector.view,
|
|
665
|
+
projectorSampler: projector.sampler,
|
|
666
|
+
}),
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Resolve the SpotLight-owned cookie independently of volumetric fog. Surface
|
|
672
|
+
* lighting must keep the authored projector when the fog component is absent;
|
|
673
|
+
* otherwise the view bind group silently falls back to white and changes the
|
|
674
|
+
* direct-light energy on the floor. A fog-selected projector is preferred so
|
|
675
|
+
* the surface and volume lanes consume one identity, with the first authored
|
|
676
|
+
* projector as the deterministic scene fallback.
|
|
677
|
+
*/
|
|
678
|
+
function prepareSpotLightProjectorFrame(
|
|
679
|
+
internals: RenderSystemInternals,
|
|
680
|
+
world: World,
|
|
681
|
+
worlds: readonly World[],
|
|
682
|
+
lights: ExtractedLights,
|
|
683
|
+
fog: ExtractedVolumetricFog | undefined,
|
|
684
|
+
): SpotLightProjectorFrameContext | undefined {
|
|
685
|
+
const preferred =
|
|
686
|
+
fog?.projectorHandle === undefined
|
|
687
|
+
? undefined
|
|
688
|
+
: lights.spot.find((light) => light.projectorHandle === fog.projectorHandle);
|
|
689
|
+
const source =
|
|
690
|
+
preferred ??
|
|
691
|
+
lights.spot.find(
|
|
692
|
+
(light) =>
|
|
693
|
+
light.projectorHandle !== undefined &&
|
|
694
|
+
light.projectorAsset !== undefined &&
|
|
695
|
+
light.lightViewProj !== undefined,
|
|
696
|
+
);
|
|
697
|
+
if (
|
|
698
|
+
source === undefined ||
|
|
699
|
+
source.projectorHandle === undefined ||
|
|
700
|
+
source.projectorAsset === undefined
|
|
701
|
+
) {
|
|
702
|
+
return undefined;
|
|
703
|
+
}
|
|
704
|
+
const ownerWorld = worlds[fog?.worldId ?? 0] ?? world;
|
|
705
|
+
const resident = internals.gpuStore.ensureResident(
|
|
706
|
+
source.projectorHandle,
|
|
707
|
+
source.projectorAsset,
|
|
708
|
+
ownerWorld,
|
|
709
|
+
);
|
|
710
|
+
if (!resident.ok || !('texture' in resident.value)) {
|
|
711
|
+
if (!resident.ok) {
|
|
712
|
+
internals.errorRegistry.fire(
|
|
713
|
+
resident.error instanceof RhiError
|
|
714
|
+
? resident.error
|
|
715
|
+
: new RhiError({
|
|
716
|
+
code: 'webgpu-runtime-error',
|
|
717
|
+
expected: 'SpotLight projector residency to resolve a GPU texture',
|
|
718
|
+
hint: 'repair the authored projector TextureAsset payload and retry the next frame',
|
|
719
|
+
detail: { error: resident.error },
|
|
720
|
+
}),
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
return undefined;
|
|
724
|
+
}
|
|
725
|
+
const sampler = internals.device.createSampler({
|
|
726
|
+
label: 'spot-projector-linear-clamp',
|
|
727
|
+
minFilter: 'linear',
|
|
728
|
+
magFilter: 'linear',
|
|
729
|
+
mipmapFilter: 'linear',
|
|
730
|
+
addressModeU: 'clamp-to-edge',
|
|
731
|
+
addressModeV: 'clamp-to-edge',
|
|
732
|
+
addressModeW: 'clamp-to-edge',
|
|
733
|
+
});
|
|
734
|
+
if (!sampler.ok) {
|
|
735
|
+
internals.errorRegistry.fire(sampler.error);
|
|
736
|
+
return undefined;
|
|
737
|
+
}
|
|
738
|
+
return {
|
|
739
|
+
texture: resident.value.texture.handle,
|
|
740
|
+
view: resident.value.view,
|
|
741
|
+
sampler: sampler.value,
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/** Stage the accepted parameter payload into the writable slot for a degraded
|
|
746
|
+
* source frame. This keeps the accepted GPU buffer immutable until submit
|
|
747
|
+
* succeeds while still allowing the LKG graph to update its history flag. */
|
|
748
|
+
function stageAcceptedVolumetricFogFrame(
|
|
749
|
+
internals: RenderSystemInternals,
|
|
750
|
+
frameState: RenderFrameState,
|
|
751
|
+
accepted: VolumetricFogFrameContext | undefined,
|
|
752
|
+
): VolumetricFogFrameContext | undefined {
|
|
753
|
+
if (accepted === undefined) return undefined;
|
|
754
|
+
const params = frameState.volumetricFogAcceptedParams;
|
|
755
|
+
if (params === undefined) return accepted;
|
|
756
|
+
const paramsBuffer = stageVolumetricFogParams(internals, frameState, new Float32Array(params));
|
|
757
|
+
if (paramsBuffer === undefined) return accepted;
|
|
758
|
+
return { ...accepted, paramsBuffer };
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function updateVolumetricFogInspection(
|
|
762
|
+
frameState: RenderFrameState,
|
|
763
|
+
fog: ExtractedVolumetricFog | undefined,
|
|
764
|
+
lights: ExtractedLights,
|
|
765
|
+
prepared: VolumetricFogFrameContext | undefined,
|
|
766
|
+
submitted: boolean,
|
|
767
|
+
volumeCapability: boolean,
|
|
768
|
+
volumeSubmissionAttempted: boolean,
|
|
769
|
+
): void {
|
|
770
|
+
const resourceFacts =
|
|
771
|
+
frameState.compiledFrameGraph === undefined || frameState.compiledFrameGraph === null
|
|
772
|
+
? undefined
|
|
773
|
+
: inspectVolumetricFogResources(frameState.compiledFrameGraph.inspect(), {
|
|
774
|
+
parameterBufferCount: frameState.volumetricFogParamsBuffers.filter(
|
|
775
|
+
(buffer) => buffer !== null,
|
|
776
|
+
).length,
|
|
777
|
+
});
|
|
778
|
+
const graphSampleCount = resourceFacts?.sampleCount ?? 0;
|
|
779
|
+
const graphMemoryBytes = resourceFacts?.totalBytes ?? 0;
|
|
780
|
+
const previous = frameState.volumetricFogInspection;
|
|
781
|
+
const accepted = frameState.volumetricFogAccepted;
|
|
782
|
+
const acceptedLkg =
|
|
783
|
+
accepted === undefined
|
|
784
|
+
? undefined
|
|
785
|
+
: {
|
|
786
|
+
guid: accepted.guid ?? previous.guid,
|
|
787
|
+
generation: accepted.generation ?? previous.generation,
|
|
788
|
+
digest: accepted.digest ?? previous.digest,
|
|
789
|
+
deviceEpoch: previous.deviceEpoch,
|
|
790
|
+
format: previous.format ?? accepted.densityAsset?.format ?? fog?.densityAsset?.format,
|
|
791
|
+
passCount: previous.passCount > 0 ? previous.passCount : VOLUMETRIC_FOG_PASS_COUNT,
|
|
792
|
+
sampleCount: previous.sampleCount > 0 ? previous.sampleCount : graphSampleCount,
|
|
793
|
+
memoryBytes: previous.memoryBytes > 0 ? previous.memoryBytes : graphMemoryBytes,
|
|
794
|
+
resourceFacts: previous.resourceFacts ?? resourceFacts,
|
|
795
|
+
lightEntity: accepted.lightEntity,
|
|
796
|
+
lightKind: accepted.lightKind,
|
|
797
|
+
pointLightEntity: accepted.pointLightEntity,
|
|
798
|
+
spotLightEntity: accepted.spotLightEntity,
|
|
799
|
+
projector: accepted.projector,
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
const candidateIdentity =
|
|
803
|
+
fog?.guid === undefined || fog.generation === undefined
|
|
804
|
+
? undefined
|
|
805
|
+
: {
|
|
806
|
+
guid: fog.guid,
|
|
807
|
+
generation: fog.generation,
|
|
808
|
+
digest: fog.digest,
|
|
809
|
+
};
|
|
810
|
+
const selectedLightAvailable =
|
|
811
|
+
fog?.lightKind === 'spot'
|
|
812
|
+
? lights.spot.some((light) => light.entity === fog.lightEntity)
|
|
813
|
+
: fog?.lightKind === 'point'
|
|
814
|
+
? lights.point.some(
|
|
815
|
+
(light) => light.entity === (fog.pointLightEntity ?? fog.lightEntity),
|
|
816
|
+
) &&
|
|
817
|
+
(fog.spotLightEntity === undefined ||
|
|
818
|
+
lights.spot.some((light) => light.entity === fog.spotLightEntity))
|
|
819
|
+
: fog?.lightKind === 'directional'
|
|
820
|
+
? lights.directional?.entity === fog.lightEntity
|
|
821
|
+
: lights.directional !== undefined;
|
|
822
|
+
const capability = volumeCapability && selectedLightAvailable ? 'available' : 'unavailable';
|
|
823
|
+
|
|
824
|
+
const inspectAccepted = (status: 'accepted' | 'degraded', candidateFailure?: 'submit-failed') => {
|
|
825
|
+
if (
|
|
826
|
+
acceptedLkg === undefined ||
|
|
827
|
+
acceptedLkg.guid === undefined ||
|
|
828
|
+
acceptedLkg.generation === undefined
|
|
829
|
+
) {
|
|
830
|
+
return false;
|
|
831
|
+
}
|
|
832
|
+
const recovery = {
|
|
833
|
+
guid: acceptedLkg.guid,
|
|
834
|
+
generation: acceptedLkg.generation,
|
|
835
|
+
deviceEpoch: acceptedLkg.deviceEpoch,
|
|
836
|
+
status,
|
|
837
|
+
...(status === 'degraded' ? { lkgGeneration: acceptedLkg.generation } : {}),
|
|
838
|
+
...(candidateIdentity === undefined
|
|
839
|
+
? {}
|
|
840
|
+
: {
|
|
841
|
+
candidateGeneration: candidateIdentity.generation,
|
|
842
|
+
...(candidateIdentity.digest === undefined
|
|
843
|
+
? {}
|
|
844
|
+
: { candidateDigest: candidateIdentity.digest }),
|
|
845
|
+
}),
|
|
846
|
+
...(acceptedLkg.lightEntity === undefined || acceptedLkg.lightKind === undefined
|
|
847
|
+
? {}
|
|
848
|
+
: {
|
|
849
|
+
selectedLight: {
|
|
850
|
+
entity: acceptedLkg.lightEntity,
|
|
851
|
+
kind: acceptedLkg.lightKind,
|
|
852
|
+
revision: 0,
|
|
853
|
+
shadowTile: -1,
|
|
854
|
+
...(acceptedLkg.pointLightEntity === undefined
|
|
855
|
+
? {}
|
|
856
|
+
: { pointLightEntity: acceptedLkg.pointLightEntity }),
|
|
857
|
+
...(acceptedLkg.spotLightEntity === undefined
|
|
858
|
+
? {}
|
|
859
|
+
: { spotLightEntity: acceptedLkg.spotLightEntity }),
|
|
860
|
+
...(acceptedLkg.projector === undefined ? {} : { projector: acceptedLkg.projector }),
|
|
861
|
+
},
|
|
862
|
+
}),
|
|
863
|
+
...(candidateFailure === undefined ? {} : { candidateFailure }),
|
|
864
|
+
} satisfies import('../volume/recovery').VolumeRecoveryState;
|
|
865
|
+
frameState.volumetricFogInspection = inspectVolumetricFog({
|
|
866
|
+
authored: true,
|
|
867
|
+
capability: 'available',
|
|
868
|
+
degraded: status === 'degraded',
|
|
869
|
+
recovery,
|
|
870
|
+
...(acceptedLkg.digest === undefined ? {} : { acceptedDigest: acceptedLkg.digest }),
|
|
871
|
+
...(acceptedLkg.format === undefined ? {} : { format: acceptedLkg.format }),
|
|
872
|
+
passCount: acceptedLkg.passCount,
|
|
873
|
+
sampleCount: acceptedLkg.sampleCount,
|
|
874
|
+
memoryBytes: acceptedLkg.memoryBytes,
|
|
875
|
+
...(acceptedLkg.resourceFacts === undefined
|
|
876
|
+
? {}
|
|
877
|
+
: { resourceFacts: acceptedLkg.resourceFacts }),
|
|
878
|
+
});
|
|
879
|
+
return true;
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
if (fog === undefined || fog.status === 'off') {
|
|
883
|
+
// A failed fog-off candidate must not erase the inspection/LKG that is
|
|
884
|
+
// still being rendered. The accepted projection is retired only after a
|
|
885
|
+
// successful no-volume submission below.
|
|
886
|
+
if (!submitted && volumeSubmissionAttempted && inspectAccepted('degraded', 'submit-failed')) {
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
if (!submitted && volumeSubmissionAttempted) return;
|
|
890
|
+
if (!submitted) return;
|
|
891
|
+
frameState.volumetricFogInspection = inspectVolumetricFog({
|
|
892
|
+
authored: false,
|
|
893
|
+
capability: 'available',
|
|
894
|
+
});
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
const authored = fog.status === 'available' || fog.status === 'degraded';
|
|
899
|
+
|
|
900
|
+
// A successfully submitted available candidate is the only path that may
|
|
901
|
+
// become the new accepted projection. This call runs after graph settlement
|
|
902
|
+
// so the inspection and the graph/context observe the same transaction.
|
|
903
|
+
if (
|
|
904
|
+
submitted &&
|
|
905
|
+
fog.status === 'available' &&
|
|
906
|
+
prepared !== undefined &&
|
|
907
|
+
capability === 'available'
|
|
908
|
+
) {
|
|
909
|
+
const recovery =
|
|
910
|
+
candidateIdentity === undefined
|
|
911
|
+
? undefined
|
|
912
|
+
: {
|
|
913
|
+
guid: candidateIdentity.guid,
|
|
914
|
+
generation: candidateIdentity.generation,
|
|
915
|
+
deviceEpoch: previous.deviceEpoch,
|
|
916
|
+
status: 'accepted' as const,
|
|
917
|
+
...(fog.lightEntity === undefined || fog.lightKind === undefined
|
|
918
|
+
? {}
|
|
919
|
+
: {
|
|
920
|
+
selectedLight: {
|
|
921
|
+
entity: fog.lightEntity,
|
|
922
|
+
kind: fog.lightKind,
|
|
923
|
+
revision: 0,
|
|
924
|
+
shadowTile:
|
|
925
|
+
lights.spot.find((spot) => spot.entity === fog.spotLightEntity)
|
|
926
|
+
?.shadowAtlasTile ??
|
|
927
|
+
lights.spot.find((spot) => spot.entity === fog.lightEntity)
|
|
928
|
+
?.shadowAtlasTile ??
|
|
929
|
+
-1,
|
|
930
|
+
...(fog.pointLightEntity === undefined
|
|
931
|
+
? {}
|
|
932
|
+
: { pointLightEntity: fog.pointLightEntity }),
|
|
933
|
+
...(fog.spotLightEntity === undefined
|
|
934
|
+
? {}
|
|
935
|
+
: { spotLightEntity: fog.spotLightEntity }),
|
|
936
|
+
...(fog.projector === undefined ? {} : { projector: fog.projector }),
|
|
937
|
+
},
|
|
938
|
+
}),
|
|
939
|
+
};
|
|
940
|
+
frameState.volumetricFogInspection = inspectVolumetricFog({
|
|
941
|
+
authored: true,
|
|
942
|
+
capability,
|
|
943
|
+
...(recovery === undefined ? {} : { recovery }),
|
|
944
|
+
...(candidateIdentity?.digest === undefined
|
|
945
|
+
? {}
|
|
946
|
+
: { acceptedDigest: candidateIdentity.digest }),
|
|
947
|
+
...(fog.densityAsset?.format === undefined ? {} : { format: fog.densityAsset.format }),
|
|
948
|
+
passCount: VOLUMETRIC_FOG_PASS_COUNT,
|
|
949
|
+
sampleCount: graphSampleCount,
|
|
950
|
+
memoryBytes: graphMemoryBytes,
|
|
951
|
+
...(resourceFacts === undefined ? {} : { resourceFacts }),
|
|
952
|
+
});
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// A submitted degraded source (or an available source whose residency
|
|
957
|
+
// preparation failed) is rendered through the previously accepted graph.
|
|
958
|
+
// Keep that LKG resource fact visible instead of projecting a zero-resource
|
|
959
|
+
// candidate merely because the current source could not be prepared.
|
|
960
|
+
if (
|
|
961
|
+
submitted &&
|
|
962
|
+
acceptedLkg !== undefined &&
|
|
963
|
+
(fog.status === 'degraded' || prepared === undefined)
|
|
964
|
+
) {
|
|
965
|
+
if (inspectAccepted('degraded')) return;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// Any candidate that reached encode/submit but failed must project the LKG,
|
|
969
|
+
// never the unsubmitted candidate. The candidate identity remains visible so
|
|
970
|
+
// recovery tooling can distinguish the rejected bytes from the frame being
|
|
971
|
+
// rendered.
|
|
972
|
+
if (!submitted && volumeSubmissionAttempted && inspectAccepted('degraded', 'submit-failed')) {
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// A degraded source that has no LKG is still a diagnostic, but it must not
|
|
977
|
+
// claim accepted resources. Keep its identity in the candidate stage.
|
|
978
|
+
const candidateRecovery =
|
|
979
|
+
candidateIdentity === undefined
|
|
980
|
+
? undefined
|
|
981
|
+
: {
|
|
982
|
+
guid: candidateIdentity.guid,
|
|
983
|
+
generation: candidateIdentity.generation,
|
|
984
|
+
deviceEpoch: previous.deviceEpoch,
|
|
985
|
+
status: 'candidate' as const,
|
|
986
|
+
candidateGeneration: candidateIdentity.generation,
|
|
987
|
+
...(candidateIdentity.digest === undefined
|
|
988
|
+
? {}
|
|
989
|
+
: { candidateDigest: candidateIdentity.digest }),
|
|
990
|
+
...(!submitted && volumeSubmissionAttempted
|
|
991
|
+
? { candidateFailure: 'submit-failed' as const }
|
|
992
|
+
: {}),
|
|
993
|
+
};
|
|
994
|
+
frameState.volumetricFogInspection = inspectVolumetricFog({
|
|
995
|
+
authored,
|
|
996
|
+
capability,
|
|
997
|
+
degraded: fog.status === 'degraded' || capability === 'unavailable',
|
|
998
|
+
...(candidateRecovery === undefined ? {} : { recovery: candidateRecovery }),
|
|
999
|
+
...(acceptedLkg?.digest === undefined ? {} : { acceptedDigest: acceptedLkg.digest }),
|
|
1000
|
+
...(fog.densityAsset?.format === undefined
|
|
1001
|
+
? acceptedLkg?.format === undefined
|
|
1002
|
+
? {}
|
|
1003
|
+
: { format: acceptedLkg.format }
|
|
1004
|
+
: { format: fog.densityAsset.format }),
|
|
1005
|
+
passCount: 0,
|
|
1006
|
+
sampleCount: 0,
|
|
1007
|
+
memoryBytes: 0,
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
|
|
292
1011
|
export function recordFrame(
|
|
293
1012
|
internals: RenderSystemInternals,
|
|
294
1013
|
world: World,
|
|
@@ -304,6 +1023,7 @@ export function recordFrame(
|
|
|
304
1023
|
skybox: SkyboxSnapshot | undefined,
|
|
305
1024
|
skyboxCount: number,
|
|
306
1025
|
postProcessParams: ReadonlyMap<string, Uint8Array>,
|
|
1026
|
+
fog: FogFrame | undefined,
|
|
307
1027
|
// feat-20260709-editor-world-partition ENGINE-fix-round2 (defect 2): the
|
|
308
1028
|
// full worlds[] list passed to `renderer.draw`, indexed by
|
|
309
1029
|
// RenderableSnapshot.worldId so the record stage resolves each renderable's
|
|
@@ -321,6 +1041,12 @@ export function recordFrame(
|
|
|
321
1041
|
renderReadLeases?: readonly RenderReadLease[],
|
|
322
1042
|
featureGraphCandidate?: RenderFeatureGraphCandidate,
|
|
323
1043
|
pointsLinesOwner?: import('./render-context').PointsLinesRecordOwner,
|
|
1044
|
+
environmentSignature = '',
|
|
1045
|
+
fogSignature = '',
|
|
1046
|
+
environmentReady = true,
|
|
1047
|
+
transmissionDemand?: TransmissionDemand,
|
|
1048
|
+
volumetricFog?: ExtractedVolumetricFog,
|
|
1049
|
+
timingCapture?: GpuTimingCapture,
|
|
324
1050
|
): boolean {
|
|
325
1051
|
// The `try / finally` wrapper advances `frameState.frameNumber` exactly
|
|
326
1052
|
// once per `recordFrame` invocation regardless of which early-return
|
|
@@ -351,6 +1077,11 @@ export function recordFrame(
|
|
|
351
1077
|
);
|
|
352
1078
|
activeCameras = [makeZeroCameraFallbackSnapshot()];
|
|
353
1079
|
}
|
|
1080
|
+
let submitted = false;
|
|
1081
|
+
let volumeInspectionReady = false;
|
|
1082
|
+
let volumeSubmissionAttempted = false;
|
|
1083
|
+
let preparedVolumetricFogForInspection: VolumetricFogFrameContext | undefined;
|
|
1084
|
+
let volumeCapabilityForInspection = false;
|
|
354
1085
|
try {
|
|
355
1086
|
// Case D: N>1 Camera => fire onError, use first hit (D-S7).
|
|
356
1087
|
if (activeCameras.length > 1) {
|
|
@@ -484,6 +1215,64 @@ export function recordFrame(
|
|
|
484
1215
|
const effectiveShadowMapSize = resolveShadowMapSize(internals, lights);
|
|
485
1216
|
const effectiveSpotShadowMapSize = resolveSpotShadowMapSize(internals, lights);
|
|
486
1217
|
const graphShadowMapSize = effectiveShadowMapSize ?? effectiveSpotShadowMapSize;
|
|
1218
|
+
const volumeCapability = hasVolumetricFogCapability(
|
|
1219
|
+
internals.device.caps,
|
|
1220
|
+
internals.volumetricFogShaders,
|
|
1221
|
+
);
|
|
1222
|
+
volumeInspectionReady = true;
|
|
1223
|
+
volumeCapabilityForInspection = volumeCapability;
|
|
1224
|
+
|
|
1225
|
+
const preparedSpotLightProjector = prepareSpotLightProjectorFrame(
|
|
1226
|
+
internals,
|
|
1227
|
+
world,
|
|
1228
|
+
worlds,
|
|
1229
|
+
lights,
|
|
1230
|
+
volumetricFog,
|
|
1231
|
+
);
|
|
1232
|
+
|
|
1233
|
+
const preparedVolumetricFog = prepareVolumetricFogFrame(
|
|
1234
|
+
internals,
|
|
1235
|
+
frameState,
|
|
1236
|
+
world,
|
|
1237
|
+
worlds,
|
|
1238
|
+
volumetricFog,
|
|
1239
|
+
lights,
|
|
1240
|
+
volumeCapability,
|
|
1241
|
+
preparedSpotLightProjector,
|
|
1242
|
+
);
|
|
1243
|
+
preparedVolumetricFogForInspection = preparedVolumetricFog;
|
|
1244
|
+
// A degraded authored snapshot must keep consuming the last accepted GPU
|
|
1245
|
+
// projection. The current source is still surfaced as a diagnostic, but
|
|
1246
|
+
// it must not replace the graph/context that produced the last good frame.
|
|
1247
|
+
// An absent component is different: a successful no-volume frame retires
|
|
1248
|
+
// the accepted projection and compiles the normal graph.
|
|
1249
|
+
const acceptedFallback =
|
|
1250
|
+
volumeCapability && volumetricFog !== undefined && preparedVolumetricFog === undefined
|
|
1251
|
+
? frameState.volumetricFogAccepted
|
|
1252
|
+
: undefined;
|
|
1253
|
+
const acceptedFallbackContext =
|
|
1254
|
+
acceptedFallback === undefined
|
|
1255
|
+
? undefined
|
|
1256
|
+
: stageAcceptedVolumetricFogFrame(
|
|
1257
|
+
internals,
|
|
1258
|
+
frameState,
|
|
1259
|
+
frameState.volumetricFogAcceptedContext,
|
|
1260
|
+
);
|
|
1261
|
+
const graphVolumetricFog = volumeCapability
|
|
1262
|
+
? preparedVolumetricFog === undefined
|
|
1263
|
+
? acceptedFallback
|
|
1264
|
+
: volumetricFog
|
|
1265
|
+
: undefined;
|
|
1266
|
+
const baseVolumetricFogContext = preparedVolumetricFog ?? acceptedFallbackContext;
|
|
1267
|
+
// A volume graph replacement is provisional whenever it can affect the
|
|
1268
|
+
// accepted volume projection. This includes authoring degradation (which
|
|
1269
|
+
// consumes the LKG graph), an authored replacement, and an explicit
|
|
1270
|
+
// fog-off transition. Non-volume frames retain the legacy immediate graph
|
|
1271
|
+
// retirement path.
|
|
1272
|
+
const volumeTopologyCandidate =
|
|
1273
|
+
(graphVolumetricFog?.status === 'available' && baseVolumetricFogContext !== undefined) ||
|
|
1274
|
+
(graphVolumetricFog === undefined && frameState.volumetricFogAccepted !== undefined) ||
|
|
1275
|
+
(volumetricFog?.status === 'degraded' && acceptedFallback !== undefined);
|
|
487
1276
|
|
|
488
1277
|
let preparedGpuDriven: PreparedGpuDrivenFrame | undefined;
|
|
489
1278
|
if (gpuDriven !== undefined) {
|
|
@@ -521,6 +1310,10 @@ export function recordFrame(
|
|
|
521
1310
|
graphShadowMapSize,
|
|
522
1311
|
preparedGpuDriven,
|
|
523
1312
|
featureGraphCandidate,
|
|
1313
|
+
cameras.length === 0,
|
|
1314
|
+
transmissionDemand,
|
|
1315
|
+
graphVolumetricFog,
|
|
1316
|
+
volumeTopologyCandidate,
|
|
524
1317
|
),
|
|
525
1318
|
);
|
|
526
1319
|
if (preflightGraph === null) return false;
|
|
@@ -539,6 +1332,108 @@ export function recordFrame(
|
|
|
539
1332
|
const targetW = swapTarget.targetW;
|
|
540
1333
|
const targetH = swapTarget.targetH;
|
|
541
1334
|
|
|
1335
|
+
const temporalView =
|
|
1336
|
+
camera.antialias === 'taa' && environmentReady
|
|
1337
|
+
? (() => {
|
|
1338
|
+
const created = createTemporalView({
|
|
1339
|
+
antialias: camera.antialias,
|
|
1340
|
+
width: targetW,
|
|
1341
|
+
height: targetH,
|
|
1342
|
+
frameIndex: frameState.successfulTemporalFrameIndex ?? 0,
|
|
1343
|
+
viewIdentity: `camera:${camera.entityKey ?? 0}`,
|
|
1344
|
+
environmentSignature,
|
|
1345
|
+
fogSignature,
|
|
1346
|
+
deviceGeneration: internals.deviceScope.generation,
|
|
1347
|
+
...(camera.historyVersion === undefined
|
|
1348
|
+
? {}
|
|
1349
|
+
: { historyVersion: camera.historyVersion }),
|
|
1350
|
+
});
|
|
1351
|
+
const previous = frameState.lastSuccessfulTemporalView;
|
|
1352
|
+
const currentUnjitteredViewProjection = mat4.multiply(
|
|
1353
|
+
mat4.create(),
|
|
1354
|
+
computeProjectionMatrix(camera),
|
|
1355
|
+
computeViewMatrix(camera),
|
|
1356
|
+
);
|
|
1357
|
+
const resetCandidate = createTemporalView({
|
|
1358
|
+
antialias: created.input.antialias,
|
|
1359
|
+
width: created.input.width,
|
|
1360
|
+
height: created.input.height,
|
|
1361
|
+
frameIndex: created.input.frameIndex,
|
|
1362
|
+
historyVersion: created.input.historyVersion,
|
|
1363
|
+
viewIdentity: created.input.viewIdentity,
|
|
1364
|
+
environmentSignature,
|
|
1365
|
+
fogSignature,
|
|
1366
|
+
deviceGeneration: internals.deviceScope.generation,
|
|
1367
|
+
cameraCut: created.input.cameraCut,
|
|
1368
|
+
historyValid: false,
|
|
1369
|
+
currentUnjitteredViewProjection,
|
|
1370
|
+
});
|
|
1371
|
+
const resetReason = resolveTemporalReset(previous, resetCandidate);
|
|
1372
|
+
return createTemporalView({
|
|
1373
|
+
...resetCandidate.input,
|
|
1374
|
+
frameIndex: resetReason === undefined ? resetCandidate.input.frameIndex : 0,
|
|
1375
|
+
historyValid: previous !== undefined && resetReason === undefined,
|
|
1376
|
+
currentUnjitteredViewProjection,
|
|
1377
|
+
resetReason,
|
|
1378
|
+
...(resetReason !== undefined ||
|
|
1379
|
+
previous?.currentUnjitteredViewProjection === undefined
|
|
1380
|
+
? {}
|
|
1381
|
+
: {
|
|
1382
|
+
previousUnjitteredViewProjection: previous.currentUnjitteredViewProjection,
|
|
1383
|
+
}),
|
|
1384
|
+
});
|
|
1385
|
+
})()
|
|
1386
|
+
: undefined;
|
|
1387
|
+
frameState.pendingTemporalCommit =
|
|
1388
|
+
cameras.length === 0 || !environmentReady || internals.deviceScope === undefined
|
|
1389
|
+
? { kind: 'none' }
|
|
1390
|
+
: temporalView === undefined
|
|
1391
|
+
? {
|
|
1392
|
+
kind: 'off',
|
|
1393
|
+
view: createTemporalView({
|
|
1394
|
+
antialias: camera.antialias,
|
|
1395
|
+
width: targetW,
|
|
1396
|
+
height: targetH,
|
|
1397
|
+
frameIndex: frameState.successfulTemporalFrameIndex ?? 0,
|
|
1398
|
+
viewIdentity: `camera:${camera.entityKey ?? 0}`,
|
|
1399
|
+
environmentSignature,
|
|
1400
|
+
fogSignature,
|
|
1401
|
+
deviceGeneration: internals.deviceScope.generation,
|
|
1402
|
+
}),
|
|
1403
|
+
}
|
|
1404
|
+
: { kind: 'taa', view: temporalView };
|
|
1405
|
+
const recordCamera: CameraSnapshot =
|
|
1406
|
+
temporalView === undefined ? camera : { ...camera, temporal: temporalView };
|
|
1407
|
+
let activeVolumetricFogContext: VolumetricFogFrameContext | undefined;
|
|
1408
|
+
let activeVolumetricFogSignature: VolumeTemporalSignature | undefined;
|
|
1409
|
+
if (graphVolumetricFog?.status === 'available' && baseVolumetricFogContext !== undefined) {
|
|
1410
|
+
const resolvedHistory = resolveVolumetricFogHistoryContext(
|
|
1411
|
+
frameState,
|
|
1412
|
+
preflightGraph,
|
|
1413
|
+
graphVolumetricFog,
|
|
1414
|
+
baseVolumetricFogContext,
|
|
1415
|
+
camera,
|
|
1416
|
+
lights,
|
|
1417
|
+
targetW,
|
|
1418
|
+
targetH,
|
|
1419
|
+
);
|
|
1420
|
+
activeVolumetricFogContext = resolvedHistory.context;
|
|
1421
|
+
activeVolumetricFogSignature = resolvedHistory.signature;
|
|
1422
|
+
const historyFlag = new Float32Array([activeVolumetricFogContext.historyValid ? 1 : 0]);
|
|
1423
|
+
if (frameState.volumetricFogPendingParams !== undefined) {
|
|
1424
|
+
frameState.volumetricFogPendingParams[31] = historyFlag[0] ?? 0;
|
|
1425
|
+
}
|
|
1426
|
+
const historyFlagWritten = internals.device.queue.writeBuffer(
|
|
1427
|
+
activeVolumetricFogContext.paramsBuffer,
|
|
1428
|
+
31 * Float32Array.BYTES_PER_ELEMENT,
|
|
1429
|
+
historyFlag,
|
|
1430
|
+
);
|
|
1431
|
+
if (!historyFlagWritten.ok) {
|
|
1432
|
+
internals.errorRegistry.fire(historyFlagWritten.error);
|
|
1433
|
+
return false;
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
|
|
542
1437
|
const depthView: TextureView | null = null;
|
|
543
1438
|
// feat-20260709 M3 / D-3: clear-color read from the active CameraSnapshot's
|
|
544
1439
|
// single `clearColor` array field (first-archetype-hit per OOS-2). When the
|
|
@@ -583,7 +1478,7 @@ export function recordFrame(
|
|
|
583
1478
|
const { tonemapActive, skyboxActive } = resolveSkyboxActive(
|
|
584
1479
|
internals,
|
|
585
1480
|
frameState,
|
|
586
|
-
|
|
1481
|
+
recordCamera,
|
|
587
1482
|
skybox,
|
|
588
1483
|
);
|
|
589
1484
|
|
|
@@ -687,7 +1582,18 @@ export function recordFrame(
|
|
|
687
1582
|
// feat-20260531-skybox-env-background M2 / w6: gate relaxed from
|
|
688
1583
|
// `validatedOrdered.length > 0` to include skybox-only frames
|
|
689
1584
|
// (plan-strategy D-3, R-3).
|
|
690
|
-
|
|
1585
|
+
const currentViewProjection = mat4.create();
|
|
1586
|
+
mat4.multiply(
|
|
1587
|
+
currentViewProjection,
|
|
1588
|
+
computeProjectionMatrix(camera),
|
|
1589
|
+
computeViewMatrix(camera),
|
|
1590
|
+
);
|
|
1591
|
+
if (
|
|
1592
|
+
validatedOrdered.length > 0 ||
|
|
1593
|
+
skyboxActive ||
|
|
1594
|
+
activeVolumetricFogContext !== undefined ||
|
|
1595
|
+
preparedVolumetricFog !== undefined
|
|
1596
|
+
) {
|
|
691
1597
|
runRecordProfilePhase(profilePhase, 'record/uploads', () => {
|
|
692
1598
|
// View UBO + CSM/spot-shadow matrix pack: assembled + uploaded in one
|
|
693
1599
|
// queue.writeBuffer round-trip. Extracted to view-ubo.ts (M3/w18) so
|
|
@@ -699,6 +1605,8 @@ export function recordFrame(
|
|
|
699
1605
|
light,
|
|
700
1606
|
lights,
|
|
701
1607
|
frameState.spotShadowSnapshots,
|
|
1608
|
+
fog,
|
|
1609
|
+
temporalView,
|
|
702
1610
|
);
|
|
703
1611
|
if (pipelineState.pointsLinesViewBuffer !== undefined) {
|
|
704
1612
|
writePointsLinesViewUbo(
|
|
@@ -783,12 +1691,29 @@ export function recordFrame(
|
|
|
783
1691
|
// errorRegistry + shader-cache lookups) surfaces (`internals` itself satisfies
|
|
784
1692
|
// `RenderSystemRuntime` so `runtime: internals` is a zero-cost reference). The
|
|
785
1693
|
// 0-consumed `skyboxCount` residual is dropped.
|
|
1694
|
+
// Camera-owned temporal controls are projected into the per-frame
|
|
1695
|
+
// post-process parameter map at record time. The extracted ECS map only
|
|
1696
|
+
// carries explicit PostProcessParams components; without this bridge the
|
|
1697
|
+
// builtin motion-blur pass receives its all-zero registration default and
|
|
1698
|
+
// becomes a no-op even though the temporal scene target is populated.
|
|
1699
|
+
const framePostProcessParams = new Map(postProcessParams);
|
|
1700
|
+
if (camera.motionBlur !== undefined) {
|
|
1701
|
+
const motionBlurParams = new Uint8Array(16);
|
|
1702
|
+
const motionBlurView = new DataView(motionBlurParams.buffer);
|
|
1703
|
+
motionBlurView.setFloat32(0, camera.motionBlur.shutterAngle, true);
|
|
1704
|
+
motionBlurView.setFloat32(4, camera.motionBlur.maxRadiusPixels, true);
|
|
1705
|
+
motionBlurView.setUint32(8, camera.motionBlur.sampleCount, true);
|
|
1706
|
+
motionBlurView.setUint32(12, temporalView?.historyValid === true ? 0 : 1, true);
|
|
1707
|
+
framePostProcessParams.set('forgeax.motion-blur', motionBlurParams);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
786
1710
|
const passCtx: _InternalRenderPipelineContext = {
|
|
787
1711
|
assets: internals.assets,
|
|
788
1712
|
world,
|
|
789
1713
|
gpuDrivenEntityKeys: gpuOwnedEntityKeys,
|
|
790
1714
|
store: internals.gpuStore,
|
|
791
1715
|
pipelineState,
|
|
1716
|
+
bloomResources: pipelineState.perPassResources.getBloomResources?.() ?? null,
|
|
792
1717
|
runtime: internals,
|
|
793
1718
|
encoder,
|
|
794
1719
|
view,
|
|
@@ -796,7 +1721,7 @@ export function recordFrame(
|
|
|
796
1721
|
targetW,
|
|
797
1722
|
targetH,
|
|
798
1723
|
currentTexture,
|
|
799
|
-
camera,
|
|
1724
|
+
camera: recordCamera,
|
|
800
1725
|
tonemapActive,
|
|
801
1726
|
geometryColorView,
|
|
802
1727
|
geometryDepthView,
|
|
@@ -817,7 +1742,16 @@ export function recordFrame(
|
|
|
817
1742
|
msaaActive,
|
|
818
1743
|
geometryColorResolveView,
|
|
819
1744
|
ldrSpriteColorView,
|
|
820
|
-
postProcessParams,
|
|
1745
|
+
postProcessParams: framePostProcessParams,
|
|
1746
|
+
...(internals.volumetricFogShaders === undefined
|
|
1747
|
+
? {}
|
|
1748
|
+
: { volumetricFogShaders: internals.volumetricFogShaders }),
|
|
1749
|
+
...(activeVolumetricFogContext === undefined
|
|
1750
|
+
? {}
|
|
1751
|
+
: { volumetricFog: activeVolumetricFogContext }),
|
|
1752
|
+
...(preparedSpotLightProjector === undefined
|
|
1753
|
+
? {}
|
|
1754
|
+
: { spotLightProjector: preparedSpotLightProjector }),
|
|
821
1755
|
dispatch: transparentDispatch,
|
|
822
1756
|
hdrpClusterBindGroup,
|
|
823
1757
|
hdrpClusterMembershipBindGroup,
|
|
@@ -831,7 +1765,21 @@ export function recordFrame(
|
|
|
831
1765
|
directionalShadowCacheReuse: directionalShadowCache.reuse,
|
|
832
1766
|
...(profilePhase !== undefined ? { profilePhase } : {}),
|
|
833
1767
|
};
|
|
834
|
-
const
|
|
1768
|
+
const stagedTemporalFrame = {
|
|
1769
|
+
frameId: frameState.frameNumber,
|
|
1770
|
+
currentViewProjection: new Float32Array(currentViewProjection),
|
|
1771
|
+
jitter: [0, 0] as [number, number],
|
|
1772
|
+
viewport: { width: targetW, height: targetH },
|
|
1773
|
+
cameraPosition: [
|
|
1774
|
+
camera.position[0] ?? 0,
|
|
1775
|
+
camera.position[1] ?? 0,
|
|
1776
|
+
camera.position[2] ?? 0,
|
|
1777
|
+
] as [number, number, number],
|
|
1778
|
+
};
|
|
1779
|
+
frameState.temporalFrameInput = stagedTemporalFrame;
|
|
1780
|
+
frameState.temporalFrameTransaction.stage(stagedTemporalFrame);
|
|
1781
|
+
volumeSubmissionAttempted = volumeTopologyCandidate || activeVolumetricFogContext !== undefined;
|
|
1782
|
+
submitted = runRecordProfilePhase(profilePhase, 'record/graph-execute', () =>
|
|
835
1783
|
executeCompiledFrameGraph(
|
|
836
1784
|
internals,
|
|
837
1785
|
frameState,
|
|
@@ -840,6 +1788,7 @@ export function recordFrame(
|
|
|
840
1788
|
profilePhase === undefined
|
|
841
1789
|
? undefined
|
|
842
1790
|
: (pass, encode) => profilePhase(graphExecutionPhase(pass.name), encode),
|
|
1791
|
+
timingCapture,
|
|
843
1792
|
),
|
|
844
1793
|
);
|
|
845
1794
|
if (submitted && !directionalShadowCache.reuse) {
|
|
@@ -847,8 +1796,66 @@ export function recordFrame(
|
|
|
847
1796
|
? directionalShadowCache.next
|
|
848
1797
|
: null;
|
|
849
1798
|
}
|
|
1799
|
+
if (submitted) {
|
|
1800
|
+
if (graphVolumetricFog === undefined) {
|
|
1801
|
+
frameState.volumetricFogAccepted = undefined;
|
|
1802
|
+
frameState.volumetricFogAcceptedContext = undefined;
|
|
1803
|
+
frameState.volumetricFogHistoryGraph = null;
|
|
1804
|
+
frameState.volumetricFogHistorySlot = null;
|
|
1805
|
+
frameState.volumetricFogHistorySignature = null;
|
|
1806
|
+
retireVolumetricFogParams(internals, frameState);
|
|
1807
|
+
} else if (
|
|
1808
|
+
activeVolumetricFogContext !== undefined &&
|
|
1809
|
+
activeVolumetricFogSignature !== undefined
|
|
1810
|
+
) {
|
|
1811
|
+
// Temporal history is graph-owned state. Promote the write slot only
|
|
1812
|
+
// after queue submission succeeds; a failed candidate keeps the
|
|
1813
|
+
// accepted graph/context/slot and retries into the same pending slot.
|
|
1814
|
+
frameState.volumetricFogHistoryGraph = preflightGraph;
|
|
1815
|
+
frameState.volumetricFogHistorySlot = activeVolumetricFogContext.historyWriteSlot;
|
|
1816
|
+
frameState.volumetricFogHistorySignature = activeVolumetricFogSignature;
|
|
1817
|
+
if (frameState.volumetricFogParamsPendingSlot !== null) {
|
|
1818
|
+
frameState.volumetricFogParamsAcceptedSlot = frameState.volumetricFogParamsPendingSlot;
|
|
1819
|
+
frameState.volumetricFogAcceptedParams =
|
|
1820
|
+
frameState.volumetricFogPendingParams === undefined
|
|
1821
|
+
? undefined
|
|
1822
|
+
: new Float32Array(frameState.volumetricFogPendingParams);
|
|
1823
|
+
frameState.volumetricFogParamsPendingSlot = null;
|
|
1824
|
+
frameState.volumetricFogPendingParams = undefined;
|
|
1825
|
+
}
|
|
1826
|
+
if (volumetricFog?.status === 'available' && preparedVolumetricFog !== undefined) {
|
|
1827
|
+
frameState.volumetricFogAccepted = volumetricFog;
|
|
1828
|
+
frameState.volumetricFogAcceptedContext = activeVolumetricFogContext;
|
|
1829
|
+
} else if (acceptedFallback !== undefined) {
|
|
1830
|
+
// The current authored source is degraded, so keep the old accepted
|
|
1831
|
+
// POD while advancing the LKG graph's ping-pong slot.
|
|
1832
|
+
frameState.volumetricFogAcceptedContext = activeVolumetricFogContext;
|
|
1833
|
+
}
|
|
1834
|
+
} else if (volumetricFog?.status === 'available' && preparedVolumetricFog !== undefined) {
|
|
1835
|
+
// Defensive fallback for a volume graph that was accepted before the
|
|
1836
|
+
// temporal context could be resolved; do not manufacture history.
|
|
1837
|
+
frameState.volumetricFogAccepted = volumetricFog;
|
|
1838
|
+
frameState.volumetricFogAcceptedContext = preparedVolumetricFog;
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
850
1841
|
return submitted;
|
|
851
1842
|
} finally {
|
|
1843
|
+
// Volume topology replacements are provisional until the queue submission
|
|
1844
|
+
// succeeds. This runs for every early-return path as well, so a swapchain,
|
|
1845
|
+
// encoder, or graph failure cannot leave a non-submitted candidate as the
|
|
1846
|
+
// next frame's accepted graph.
|
|
1847
|
+
settleVolumetricFogGraphCandidate(frameState, submitted);
|
|
1848
|
+
if (volumeInspectionReady && (submitted || volumeSubmissionAttempted)) {
|
|
1849
|
+
updateVolumetricFogInspection(
|
|
1850
|
+
frameState,
|
|
1851
|
+
volumetricFog,
|
|
1852
|
+
lights,
|
|
1853
|
+
preparedVolumetricFogForInspection,
|
|
1854
|
+
submitted,
|
|
1855
|
+
volumeCapabilityForInspection,
|
|
1856
|
+
volumeSubmissionAttempted,
|
|
1857
|
+
);
|
|
1858
|
+
}
|
|
852
1859
|
frameState.frameNumber += 1;
|
|
853
1860
|
// feat-20260608-cluster-lighting M5 / w22: clear HDRP once-per-frame fired
|
|
854
1861
|
// set so the next frame re-fires if the condition persists.
|