@forgeax/engine-render 0.1.28 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +627 -124
- package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
- package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/dynamic-geometry-host.d.ts +21 -0
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts +20 -0
- package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +3 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/gpu-driven-owner.d.ts +10 -0
- package/dist/assembly/gpu-driven-owner.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +8 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +7 -0
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material-shader-policy.d.ts +3 -1
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/recovery/failure-location.d.ts +12 -0
- package/dist/assembly/recovery/failure-location.d.ts.map +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts +6 -4
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts +5 -0
- package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -0
- package/dist/assembly/renderer-frame-transaction.d.ts +19 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-helpers.d.ts +3 -0
- package/dist/assembly/renderer-helpers.d.ts.map +1 -1
- package/dist/assembly/renderer-inspection.d.ts +4 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +6 -0
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
- package/dist/assembly/skin-palette-owner.d.ts +8 -0
- package/dist/assembly/skin-palette-owner.d.ts.map +1 -0
- package/dist/assembly/ssr-shader-prewarm.d.ts +6 -0
- package/dist/assembly/ssr-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/webgpu-device-loss.d.ts +15 -0
- package/dist/assembly/webgpu-device-loss.d.ts.map +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts +38 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready-mipmap.d.ts +11 -0
- package/dist/assembly/webgpu-ready-mipmap.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +7 -3
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts +10 -0
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-contract.d.ts +62 -0
- package/dist/assembly/webgpu-renderer-contract.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-guards.d.ts +9 -0
- package/dist/assembly/webgpu-renderer-guards.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-observation.d.ts +6 -0
- package/dist/assembly/webgpu-renderer-observation.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-recovery-failure.d.ts +12 -0
- package/dist/assembly/webgpu-renderer-recovery-failure.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +7 -141
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/assembly/webgpu-vertex-layouts.d.ts +28 -84
- package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
- package/dist/authoring.mjs +2 -2
- package/dist/{chunk-JAASCMXA.mjs → chunk-33XZFTQU.mjs} +245 -39
- package/dist/chunk-33XZFTQU.mjs.map +1 -0
- package/dist/{chunk-GF523LHF.mjs → chunk-BLXGONR2.mjs} +30 -12
- package/dist/chunk-BLXGONR2.mjs.map +1 -0
- package/dist/{chunk-J52NMQKR.mjs → chunk-BQVQOQJH.mjs} +1086 -838
- package/dist/chunk-BQVQOQJH.mjs.map +1 -0
- package/dist/{chunk-IQMKJLNU.mjs → chunk-BTWH7BP4.mjs} +386 -17
- package/dist/chunk-BTWH7BP4.mjs.map +1 -0
- package/dist/{chunk-MBU4ZVE7.mjs → chunk-FUODTTIA.mjs} +3921 -671
- package/dist/chunk-FUODTTIA.mjs.map +1 -0
- package/dist/{chunk-MYJ5RPJO.mjs → chunk-JQTSEI3Z.mjs} +3 -3
- package/dist/{chunk-MYJ5RPJO.mjs.map → chunk-JQTSEI3Z.mjs.map} +1 -1
- package/dist/{chunk-GE3SDD72.mjs → chunk-NICXSHAT.mjs} +16 -38
- package/dist/chunk-NICXSHAT.mjs.map +1 -0
- package/dist/{chunk-J6KACNOH.mjs → chunk-NRNXBLIJ.mjs} +577 -7
- package/dist/chunk-NRNXBLIJ.mjs.map +1 -0
- package/dist/{chunk-RBDBZ5R7.mjs → chunk-PA5DRJNI.mjs} +2 -2
- package/dist/chunk-PA5DRJNI.mjs.map +1 -0
- package/dist/{chunk-VSL23LZE.mjs → chunk-S4DNKQYQ.mjs} +1117 -445
- package/dist/chunk-S4DNKQYQ.mjs.map +1 -0
- package/dist/components/camera.d.ts +62 -2
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +6 -20
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/components/scene-instance.d.ts +2 -1
- package/dist/components/scene-instance.d.ts.map +1 -1
- package/dist/components/screen-space-reflection.d.ts +14 -0
- package/dist/components/screen-space-reflection.d.ts.map +1 -0
- package/dist/construct-renderer.mjs +12888 -7025
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +1 -12
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/environment/background.d.ts +6 -0
- package/dist/environment/background.d.ts.map +1 -0
- package/dist/errors/gpu-driven.d.ts +6 -3
- package/dist/errors/gpu-driven.d.ts.map +1 -1
- package/dist/errors/render.d.ts +7 -4
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +33 -3
- package/dist/extract/gpu-driven.d.ts.map +1 -1
- package/dist/features/host.d.ts +23 -1
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/noise-texture.d.ts +17 -0
- package/dist/features/noise-texture.d.ts.map +1 -0
- package/dist/features/plan.d.ts +83 -2
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +37 -4
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics-store.d.ts.map +1 -1
- package/dist/features/prepared-graphics.d.ts +5 -0
- package/dist/features/prepared-graphics.d.ts.map +1 -1
- package/dist/features/render-graph-compute.d.ts +5 -3
- package/dist/features/render-graph-compute.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +11 -3
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +19 -3
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/types.d.ts +11 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +2 -0
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +34 -1
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/pbr-program.d.ts +10 -0
- package/dist/gpu-driven/pbr-program.d.ts.map +1 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +144 -23
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/shadow-views.d.ts +126 -0
- package/dist/gpu-driven/shadow-views.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +18 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts +2 -8
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +14 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-texture-usage.d.ts +1 -0
- package/dist/gpu-texture-usage.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +6 -0
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/frame-resources.d.ts +8 -0
- package/dist/ibl/frame-resources.d.ts.map +1 -0
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +18 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +8 -8
- package/dist/inspection-types.d.ts +164 -0
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances-derived-bounds.d.ts +11 -0
- package/dist/instances-derived-bounds.d.ts.map +1 -1
- package/dist/instances.d.ts +89 -44
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.d.ts +3 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +117 -9
- package/dist/internal.mjs.map +1 -1
- package/dist/lifecycle.d.ts +2 -1
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/material-row.d.ts +5 -0
- package/dist/material-row.d.ts.map +1 -0
- package/dist/materials.d.ts +15 -0
- package/dist/materials.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +21 -5
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-output/auto-exposure/capability.d.ts +12 -0
- package/dist/pipeline/standard-output/auto-exposure/capability.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts +70 -0
- package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/graph.d.ts +75 -0
- package/dist/pipeline/standard-output/auto-exposure/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts +111 -0
- package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts +16 -0
- package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/preset.d.ts +14 -0
- package/dist/pipeline/standard-output/auto-exposure/preset.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/state.d.ts +46 -0
- package/dist/pipeline/standard-output/auto-exposure/state.d.ts.map +1 -0
- package/dist/pipeline/standard-output/color-transform.d.ts +27 -0
- package/dist/pipeline/standard-output/color-transform.d.ts.map +1 -0
- package/dist/pipeline/standard-output/graph.d.ts +15 -0
- package/dist/pipeline/standard-output/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-output/lut-admission.d.ts +29 -0
- package/dist/pipeline/standard-output/lut-admission.d.ts.map +1 -0
- package/dist/pipeline/standard-output/lut-gpu.d.ts +48 -0
- package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -0
- package/dist/pipeline/standard-output/lut-state.d.ts +68 -0
- package/dist/pipeline/standard-output/lut-state.d.ts.map +1 -0
- package/dist/pipeline/standard-output/resources.d.ts +10 -0
- package/dist/pipeline/standard-output/resources.d.ts.map +1 -0
- package/dist/pipeline/standard-output/types.d.ts +39 -0
- package/dist/pipeline/standard-output/types.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +2 -2
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +2 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec-types.d.ts +4 -0
- package/dist/pipeline-spec-types.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +1 -9
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/points-lines/standard-owner.d.ts +1 -1
- package/dist/points-lines/standard-owner.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +6 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/record/dynamic-geometry-consumption.d.ts +15 -0
- package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +3 -3
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +106 -5
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +39 -4
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +7 -8
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +38 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +2 -10
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +12 -2
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +15 -6
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/prepared-material-bindings.d.ts +19 -0
- package/dist/record/prepared-material-bindings.d.ts.map +1 -0
- package/dist/record/recovery-pipeline.d.ts +2 -9
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +74 -26
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +62 -7
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +35 -7
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +1 -0
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +10 -2
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/recovery/render-system-roots.d.ts +11 -0
- package/dist/recovery/render-system-roots.d.ts.map +1 -0
- package/dist/recovery/types.d.ts +76 -0
- package/dist/recovery/types.d.ts.map +1 -0
- package/dist/reflection/record-owner.d.ts +0 -2
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +173 -30
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +1 -0
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +64 -5
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +7 -5
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +101 -41
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-projections.d.ts +22 -0
- package/dist/render-system-projections.d.ts.map +1 -0
- package/dist/render-system.d.ts +27 -77
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene-types.d.ts +14 -7
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +29 -11
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/shadow-visibility.d.ts +5 -0
- package/dist/scene/shadow-visibility.d.ts.map +1 -0
- package/dist/ssr/admission.d.ts +70 -1
- package/dist/ssr/admission.d.ts.map +1 -1
- package/dist/ssr/compose.d.ts +13 -0
- package/dist/ssr/compose.d.ts.map +1 -0
- package/dist/ssr/errors.d.ts +35 -0
- package/dist/ssr/errors.d.ts.map +1 -1
- package/dist/ssr/graph.d.ts +60 -0
- package/dist/ssr/graph.d.ts.map +1 -0
- package/dist/ssr/history.d.ts +97 -0
- package/dist/ssr/history.d.ts.map +1 -0
- package/dist/ssr/hiz.d.ts +37 -0
- package/dist/ssr/hiz.d.ts.map +1 -0
- package/dist/ssr/inspection.d.ts +42 -0
- package/dist/ssr/inspection.d.ts.map +1 -0
- package/dist/ssr/resources.d.ts +58 -0
- package/dist/ssr/resources.d.ts.map +1 -0
- package/dist/ssr/temporal.d.ts +38 -0
- package/dist/ssr/temporal.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +32 -10
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/systems/skin-palette-types.d.ts +15 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -1
- package/dist/systems/transparent-dispatch.d.ts +9 -0
- package/dist/systems/transparent-dispatch.d.ts.map +1 -0
- package/dist/targets/material-source.d.ts +7 -0
- package/dist/targets/material-source.d.ts.map +1 -1
- package/dist/temporal/frame-coordinator.d.ts +7 -0
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts +8 -0
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/history.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -6
- package/dist/temporal/inspection.d.ts.map +1 -1
- package/dist/temporal/standard-scene-data.d.ts +2 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/temporal-view.d.ts +2 -0
- package/dist/temporal/temporal-view.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +35 -1
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +3 -1
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/temporal.d.ts +6 -0
- package/dist/volume/temporal.d.ts.map +1 -1
- package/package.json +21 -20
- package/src/__tests__/auto-exposure-gpu-evidence.ts +291 -0
- package/src/__tests__/auto-exposure-inspection.unit.test.ts +80 -0
- package/src/__tests__/auto-exposure-transaction.integration.test.ts +99 -0
- package/src/__tests__/auto-exposure.browser.test.ts +33 -0
- package/src/__tests__/auto-exposure.dawn.test.ts +33 -0
- package/src/__tests__/detached-inspection.integration.test.ts +5 -0
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +18 -0
- package/src/__tests__/device-scope-stale-matrix.unit.test.ts +18 -0
- package/src/__tests__/docs-gate-green.unit.test.ts +3 -3
- package/src/__tests__/factory-contract.integration.test.ts +67 -8
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +19 -0
- package/src/__tests__/feature-depth-input.dawn.test.ts +121 -0
- package/src/__tests__/feature-noise.unit.test.ts +38 -0
- package/src/__tests__/fixtures/taa-resolve-pinned-baseline.wgsl +301 -0
- package/src/__tests__/frame-camera-selection.unit.test.ts +131 -0
- package/src/__tests__/frame-plan-contract.unit.test.ts +24 -0
- package/src/__tests__/frame-targets.unit.test.ts +24 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +3 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +79 -0
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +287 -6
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +122 -142
- package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +10 -1
- package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +264 -0
- package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +349 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1417 -0
- package/src/__tests__/gpu-driven-pbr.integration.test.ts +21 -0
- package/src/__tests__/gpu-driven-production-fixture.ts +96 -0
- package/src/__tests__/gpu-driven-production.integration.test.ts +1075 -93
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +1 -3
- package/src/__tests__/gpu-driven-shadow-views.browser.test.ts +63 -0
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +294 -0
- package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +97 -0
- package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +168 -0
- package/src/__tests__/gpu-driven-skin-contract.test-d.ts +11 -0
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +72 -20
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +30 -9
- package/src/__tests__/gpu-driven-view.unit.test.ts +159 -52
- package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -1
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +42 -0
- package/src/__tests__/gpu-scene-render-graph-gpu.ts +19 -5
- package/src/__tests__/gpu-scene.dawn.test.ts +40 -13
- package/src/__tests__/gpu-scene.unit.test.ts +559 -33
- package/src/__tests__/instances-culling.integration.test.ts +36 -10
- package/src/__tests__/instances-derived-bounds.unit.test.ts +54 -0
- package/src/__tests__/instances-store.unit.test.ts +242 -39
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +6 -0
- package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +13 -16
- package/src/__tests__/lut-lkg-transaction.integration.test.ts +122 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +5 -6
- package/src/__tests__/material-dispatch-shader-id.unit.test.ts +51 -0
- package/src/__tests__/material-lane-selection.unit.test.ts +60 -0
- package/src/__tests__/material-numeric-upload.unit.test.ts +53 -0
- package/src/__tests__/material-texture-handles.unit.test.ts +18 -0
- package/src/__tests__/material-texture-source.unit.test.ts +87 -0
- package/src/__tests__/materials-authoring-validation.unit.test.ts +41 -0
- package/src/__tests__/materials-standard-contract.unit.test.ts +52 -2
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
- package/src/__tests__/normal-fallback.dawn.test.ts +122 -0
- package/src/__tests__/particle-material-input-layout.unit.test.ts +104 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +37 -3
- package/src/__tests__/pipeline-texture-specialization.unit.test.ts +138 -0
- package/src/__tests__/point-shadow-inspection.unit.test.ts +2 -0
- package/src/__tests__/prepared-gpu-driven-pbr-contract.test-d.ts +31 -0
- package/src/__tests__/prepared-gpu-driven-pbr-contract.unit.test.ts +39 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +35 -4
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +21 -0
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +6 -2
- package/src/__tests__/profiler-phase-catalog.test.ts +5 -0
- package/src/__tests__/public-surface.test-d.ts +3 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +30 -12
- package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +104 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +2 -1
- package/src/__tests__/render-error-code-owner.test-d.ts +4 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +22 -0
- package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
- package/src/__tests__/render-feature-gpu-work.integration.test.ts +285 -2
- package/src/__tests__/render-feature-plan.unit.test.ts +245 -0
- package/src/__tests__/render-feature-shadow-order.unit.test.ts +228 -0
- package/src/__tests__/render-feature-zero-work.unit.test.ts +35 -1
- package/src/__tests__/render-graph-fallback.integration.test.ts +2 -2
- package/src/__tests__/render-owner-cohesion.unit.test.ts +55 -0
- package/src/__tests__/render-scene-mixed-updates.integration.test.ts +426 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +914 -23
- package/src/__tests__/render-scene-resource-updates.integration.test.ts +214 -0
- package/src/__tests__/render-scene-skin-lifecycle.integration.test.ts +173 -0
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +133 -0
- package/src/__tests__/render-target-material-source.test-d.ts +27 -3
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +60 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
- package/src/__tests__/shader-manifest-fixture.ts +39 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +0 -33
- package/src/__tests__/skin-palette-persistent.integration.test.ts +28 -0
- package/src/__tests__/skin-palette-persistent.unit.test.ts +247 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +118 -14
- package/src/__tests__/specular-environment-scale.dawn.test.ts +156 -0
- package/src/__tests__/ssr-admission-matrix.integration.test.ts +7 -1
- package/src/__tests__/ssr-confidence-compose.unit.test.ts +84 -0
- package/src/__tests__/ssr-coordinate-oracle.unit.test.ts +28 -0
- package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +91 -0
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +112 -0
- package/src/__tests__/ssr-gpu-dispatch.ts +946 -0
- package/src/__tests__/ssr-graph-topology.unit.test.ts +104 -0
- package/src/__tests__/ssr-history-filter.dawn.test.ts +198 -0
- package/src/__tests__/ssr-hit-color.dawn.test.ts +273 -0
- package/src/__tests__/ssr-hiz-odd-reduction.dawn.test.ts +569 -0
- package/src/__tests__/ssr-hiz-rescue.dawn.test.ts +279 -0
- package/src/__tests__/ssr-hiz.browser.test.ts +150 -0
- package/src/__tests__/ssr-hiz.dawn.test.ts +150 -0
- package/src/__tests__/ssr-hiz.unit.test.ts +56 -0
- package/src/__tests__/ssr-inspection.unit.test.ts +105 -0
- package/src/__tests__/ssr-memory-budget.unit.test.ts +45 -0
- package/src/__tests__/ssr-performance-sequence-aggregation.unit.test.ts +15 -0
- package/src/__tests__/ssr-public-surface.test-d.ts +37 -0
- package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +387 -0
- package/src/__tests__/ssr-reflection-mip-reducer.dawn.test.ts +309 -0
- package/src/__tests__/ssr-reprojection-probe.ts +90 -0
- package/src/__tests__/ssr-roughness-mip.dawn.test.ts +163 -0
- package/src/__tests__/ssr-shader-prewarm.unit.test.ts +59 -0
- package/src/__tests__/ssr-spatial.integration.test.ts +141 -0
- package/src/__tests__/ssr-stable-lattice.dawn.test.ts +475 -0
- package/src/__tests__/ssr-temporal-history.unit.test.ts +202 -0
- package/src/__tests__/ssr-texel-crossing.dawn.test.ts +448 -0
- package/src/__tests__/ssr-zero-work.integration.test.ts +87 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +44 -12
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +29 -0
- package/src/__tests__/standard-output-chain-contract.unit.test.ts +99 -0
- package/src/__tests__/standard-output-chain.integration.test.ts +73 -0
- package/src/__tests__/standard-output-gpu-evidence.ts +205 -0
- package/src/__tests__/standard-output.browser.test.ts +15 -0
- package/src/__tests__/standard-output.dawn.test.ts +15 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +38 -0
- package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
- package/src/__tests__/standard-profile-oracle.unit.test.ts +22 -0
- package/src/__tests__/standard-surface-lighting.unit.test.ts +41 -0
- package/src/__tests__/standard-texture-specialization.dawn.test.ts +141 -0
- package/src/__tests__/surface-adjacent-regressions.integration.test.ts +6 -3
- package/src/__tests__/taa-coverage-edge.dawn.test.ts +193 -0
- package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
- package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +778 -0
- package/src/__tests__/taa-stability-feedback.browser.test.ts +23 -0
- package/src/__tests__/taa-stability-feedback.dawn.test.ts +68 -0
- package/src/__tests__/taa-stability-feedback.ts +341 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +49 -7
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +9 -0
- package/src/__tests__/temporal-transaction.integration.test.ts +28 -0
- package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +109 -4
- package/src/__tests__/typed-scene-pass-material-cache.integration.test.ts +126 -0
- package/src/__tests__/vertex-layouts-ssot.unit.test.ts +47 -0
- package/src/__tests__/visibility-extract.perf.test.ts +20 -8
- package/src/__tests__/visibility-instances.integration.test.ts +19 -7
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +20 -9
- package/src/assembly/atmosphere-shader-prewarm.ts +38 -0
- package/src/assembly/dynamic-geometry-host.ts +48 -0
- package/src/assembly/dynamic-geometry-runtime.ts +71 -0
- package/src/assembly/factory.ts +4 -0
- package/src/assembly/gpu-driven-owner.ts +29 -0
- package/src/assembly/host-contract.ts +10 -0
- package/src/assembly/material/assembly.ts +38 -0
- package/src/assembly/material-shader-policy.ts +71 -28
- package/src/assembly/recovery/failure-location.ts +62 -0
- package/src/assembly/recovery/renderer-recover.ts +19 -17
- package/src/assembly/renderer-facade.ts +12 -0
- package/src/assembly/renderer-feature-inspection.ts +13 -0
- package/src/assembly/renderer-frame-transaction.ts +63 -0
- package/src/assembly/renderer-helpers.ts +26 -0
- package/src/assembly/renderer-inspection.ts +6 -0
- package/src/assembly/shader-prewarm-policy.ts +32 -0
- package/src/assembly/skin-palette-owner.ts +21 -0
- package/src/assembly/ssr-shader-prewarm.ts +41 -0
- package/src/assembly/webgpu-device-loss.ts +75 -0
- package/src/assembly/webgpu-pbr-ready.ts +232 -0
- package/src/assembly/webgpu-ready-mipmap.ts +26 -0
- package/src/assembly/webgpu-ready.ts +142 -121
- package/src/assembly/webgpu-renderer-bootstrap.ts +85 -0
- package/src/assembly/webgpu-renderer-contract.ts +69 -0
- package/src/assembly/webgpu-renderer-guards.ts +32 -0
- package/src/assembly/webgpu-renderer-observation.ts +43 -0
- package/src/assembly/webgpu-renderer-recovery-failure.ts +62 -0
- package/src/assembly/webgpu-renderer.ts +666 -652
- package/src/assembly/webgpu-vertex-layouts.ts +233 -87
- package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
- package/src/components/camera.ts +287 -7
- package/src/components/index.ts +1 -0
- package/src/components/instances.ts +45 -18
- package/src/components/scene-instance.ts +2 -1
- package/src/components/screen-space-reflection.ts +21 -0
- package/src/components/sprite-animation.ts +2 -2
- package/src/components/sprite-instances.ts +1 -1
- package/src/device/gpu-residency.ts +34 -31
- package/src/environment/background.ts +263 -0
- package/src/errors/gpu-driven.ts +39 -5
- package/src/errors/render.ts +27 -3
- package/src/extract/camera.ts +26 -1
- package/src/extract/gpu-driven.ts +185 -10
- package/src/features/host.ts +237 -19
- package/src/features/noise-texture.ts +91 -0
- package/src/features/plan.ts +553 -24
- package/src/features/prepared-gpu-work.ts +631 -49
- package/src/features/prepared-graphics-store.ts +31 -0
- package/src/features/prepared-graphics.ts +5 -0
- package/src/features/render-graph-compute.ts +41 -8
- package/src/features/render-graph-contribution.ts +141 -3
- package/src/features/render-graph-raster.ts +143 -30
- package/src/features/types.ts +11 -0
- package/src/fullscreen-post-process-pass.ts +3 -0
- package/src/gpu-driven/batch-topology.ts +424 -102
- package/src/gpu-driven/pbr-program.ts +31 -0
- package/src/gpu-driven/prepared-draw.ts +29 -4
- package/src/gpu-driven/production-raster.ts +2267 -694
- package/src/gpu-driven/shadow-views.ts +539 -0
- package/src/gpu-driven/view-gpu.ts +188 -41
- package/src/gpu-scene-schema.ts +52 -11
- package/src/gpu-scene.ts +186 -99
- package/src/gpu-texture-usage.ts +1 -0
- package/src/hdrp-buffers.ts +72 -36
- package/src/ibl/frame-resources.ts +38 -0
- package/src/ibl/skylight-bind-group.ts +5 -4
- package/src/index.ts +109 -1
- package/src/inspection-types.ts +191 -0
- package/src/instances-derived-bounds.ts +258 -34
- package/src/instances.ts +459 -150
- package/src/internal.ts +22 -0
- package/src/lifecycle.ts +2 -0
- package/src/material-row.ts +145 -0
- package/src/materials.ts +44 -8
- package/src/pbr-pipeline.ts +159 -17
- package/src/pipeline/standard-forward-lane.ts +52 -24
- package/src/pipeline/standard-output/__tests__/lut-admission.unit.test.ts +103 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/capability.unit.test.ts +40 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/gpu.contract.unit.test.ts +125 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/graph.contract.unit.test.ts +94 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/oracle.test.ts +108 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/preset.test.ts +26 -0
- package/src/pipeline/standard-output/auto-exposure/capability.ts +38 -0
- package/src/pipeline/standard-output/auto-exposure/gpu.ts +567 -0
- package/src/pipeline/standard-output/auto-exposure/graph.ts +221 -0
- package/src/pipeline/standard-output/auto-exposure/inspection.ts +231 -0
- package/src/pipeline/standard-output/auto-exposure/oracle.ts +291 -0
- package/src/pipeline/standard-output/auto-exposure/preset.ts +28 -0
- package/src/pipeline/standard-output/auto-exposure/state.ts +156 -0
- package/src/pipeline/standard-output/color-transform.ts +124 -0
- package/src/pipeline/standard-output/graph.ts +139 -0
- package/src/pipeline/standard-output/lut-admission.ts +121 -0
- package/src/pipeline/standard-output/lut-gpu.ts +399 -0
- package/src/pipeline/standard-output/lut-state.ts +176 -0
- package/src/pipeline/standard-output/resources.ts +121 -0
- package/src/pipeline/standard-output/types.ts +58 -0
- package/src/pipeline/standard-pipeline.ts +192 -59
- package/src/pipeline/standard-post.ts +186 -27
- package/src/pipeline-builder.ts +16 -6
- package/src/pipeline-spec-types.ts +4 -0
- package/src/pipeline-spec.ts +37 -29
- package/src/points-lines/standard-owner.ts +6 -14
- package/src/prepare/prepared-graphics-resolver.ts +9 -2
- package/src/record/__tests__/material-slot-plan.unit.test.ts +48 -0
- package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +2 -29
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +36 -5
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +45 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +5 -0
- package/src/record/dynamic-geometry-consumption.ts +59 -0
- package/src/record/frame-lighting.ts +12 -11
- package/src/record/frame-snapshot.ts +133 -23
- package/src/record/frame-targets.ts +9 -0
- package/src/record/frame.ts +725 -133
- package/src/record/main-pass-geometry.ts +149 -94
- package/src/record/main-pass-material.ts +115 -26
- package/src/record/main-pass-sprite-draws.ts +16 -107
- package/src/record/main-pass.ts +78 -8
- package/src/record/material-uniforms.ts +1 -1
- package/src/record/mesh-ssbo.ts +59 -15
- package/src/record/prepared-material-bindings.ts +234 -0
- package/src/record/recovery-pipeline.ts +59 -136
- package/src/record/render-context.ts +90 -22
- package/src/record/shadow-pass.ts +1231 -209
- package/src/record/skybox-post-pass.ts +14 -3
- package/src/record/typed-frame-graph.ts +1004 -44
- package/src/record/view-ubo.ts +11 -0
- package/src/recovery/render-system-candidate.ts +90 -66
- package/src/recovery/render-system-roots.ts +113 -0
- package/src/recovery/types.ts +77 -0
- package/src/reflection/record-owner.ts +26 -54
- package/src/render-contract.ts +195 -25
- package/src/render-graph-primitives.ts +6 -2
- package/src/render-pipeline.ts +70 -1
- package/src/render-system-extract-tail.ts +409 -160
- package/src/render-system-extract.ts +376 -102
- package/src/render-system-projections.ts +241 -0
- package/src/render-system.ts +681 -822
- package/src/scene/render-scene-types.ts +13 -4
- package/src/scene/render-scene.ts +569 -355
- package/src/scene/shadow-visibility.ts +21 -0
- package/src/ssr/admission.ts +380 -14
- package/src/ssr/compose.ts +144 -0
- package/src/ssr/errors.ts +48 -0
- package/src/ssr/graph.ts +777 -0
- package/src/ssr/history.ts +436 -0
- package/src/ssr/hiz.ts +124 -0
- package/src/ssr/inspection.ts +124 -0
- package/src/ssr/resources.ts +202 -0
- package/src/ssr/temporal.ts +164 -0
- package/src/systems/skin-palette-allocator.ts +495 -148
- package/src/systems/skin-palette-types.ts +17 -0
- package/src/systems/transparent-dispatch.ts +90 -0
- package/src/targets/material-source.ts +34 -0
- package/src/temporal/coverage.ts +1 -1
- package/src/temporal/frame-coordinator.ts +23 -2
- package/src/temporal/gpu.ts +74 -12
- package/src/temporal/history.ts +3 -1
- package/src/temporal/inspection.ts +2 -1
- package/src/temporal/standard-scene-data.ts +3 -1
- package/src/temporal/temporal-view.ts +3 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +204 -139
- package/src/typed-render-graph-primitives.ts +266 -74
- package/src/typed-shadow-passes.ts +122 -12
- package/src/volume/temporal.ts +10 -0
- package/dist/chunk-GE3SDD72.mjs.map +0 -1
- package/dist/chunk-GF523LHF.mjs.map +0 -1
- package/dist/chunk-IQMKJLNU.mjs.map +0 -1
- package/dist/chunk-J52NMQKR.mjs.map +0 -1
- package/dist/chunk-J6KACNOH.mjs.map +0 -1
- package/dist/chunk-JAASCMXA.mjs.map +0 -1
- package/dist/chunk-MBU4ZVE7.mjs.map +0 -1
- package/dist/chunk-RBDBZ5R7.mjs.map +0 -1
- package/dist/chunk-VSL23LZE.mjs.map +0 -1
- package/src/__tests__/instances-world-ownership.integration.test.ts +0 -62
- package/src/scene/__tests__/changed-block-summary.candidate.test.ts +0 -36
|
@@ -25,10 +25,19 @@ import { executeRendererFrameTransaction } from '../assembly/renderer-frame-tran
|
|
|
25
25
|
import { type RenderError, RenderFeatureStageFailedError } from '../errors/render';
|
|
26
26
|
import {
|
|
27
27
|
getRenderFeaturePlanExecutionProjection,
|
|
28
|
+
hasSubmissionSensitiveFeatures,
|
|
28
29
|
type RenderFeaturePlanExecution,
|
|
29
30
|
} from '../features/host';
|
|
30
|
-
import {
|
|
31
|
-
|
|
31
|
+
import {
|
|
32
|
+
type RenderFeaturePlannedFrame,
|
|
33
|
+
renderFeaturePlanSignature,
|
|
34
|
+
renderFeaturePlanSignatureEvidenceMatches,
|
|
35
|
+
} from '../features/plan';
|
|
36
|
+
import {
|
|
37
|
+
createRenderFeatureProjectionState,
|
|
38
|
+
projectRenderFeaturePlans as projectPlanExecutions,
|
|
39
|
+
projectRenderFeatureShadows,
|
|
40
|
+
} from '../features/render-graph-contribution';
|
|
32
41
|
import type {
|
|
33
42
|
RenderFeatureGraphBindingsResolution,
|
|
34
43
|
RenderFeatureGraphTargetResolver,
|
|
@@ -46,12 +55,26 @@ import {
|
|
|
46
55
|
GPU_TEXTURE_USAGE_COPY_DST,
|
|
47
56
|
GPU_TEXTURE_USAGE_COPY_SRC,
|
|
48
57
|
GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
|
|
58
|
+
GPU_TEXTURE_USAGE_STORAGE_BINDING,
|
|
49
59
|
GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
50
60
|
} from '../gpu-texture-usage';
|
|
61
|
+
import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from '../gpu-usage';
|
|
62
|
+
import { createStandardSurfaceLightingBindGroup } from '../hdrp-buffers';
|
|
63
|
+
import type { RenderFeatureGraphInspection } from '../inspection-types';
|
|
51
64
|
import {
|
|
52
65
|
type StandardTopologyInputValue,
|
|
53
66
|
standardLightingTopologySignature,
|
|
54
67
|
} from '../pipeline/standard-lighting/topology';
|
|
68
|
+
import {
|
|
69
|
+
importAutoExposureGraphResources,
|
|
70
|
+
retireAutoExposureGpuResources,
|
|
71
|
+
} from '../pipeline/standard-output/auto-exposure/gpu';
|
|
72
|
+
import { commitAutoExposureSubmission } from '../pipeline/standard-output/auto-exposure/state';
|
|
73
|
+
import { retireStandardLutGpuResources } from '../pipeline/standard-output/lut-gpu';
|
|
74
|
+
import {
|
|
75
|
+
commitStandardLutCandidate,
|
|
76
|
+
resetStandardLutState,
|
|
77
|
+
} from '../pipeline/standard-output/lut-state';
|
|
55
78
|
import { resolveVolumetricFogProfile, STANDARD_PIPELINE_ID } from '../pipeline/standard-profile';
|
|
56
79
|
import type { CameraSnapshot } from '../render-contract';
|
|
57
80
|
import type {
|
|
@@ -61,7 +84,7 @@ import type {
|
|
|
61
84
|
} from '../render-pipeline';
|
|
62
85
|
import type { ExtractedLights, ExtractedVolumetricFog } from '../render-system-extract';
|
|
63
86
|
import { SHADOW_ATLAS_DEFAULT_FACE_SIZE, SHADOW_ATLAS_DEFAULT_LAYERS } from '../shadow-atlas';
|
|
64
|
-
import type { SsrAdmissionResult } from '../ssr/admission';
|
|
87
|
+
import type { SsrAdmissionResult, SsrSpatialAdmission } from '../ssr/admission';
|
|
65
88
|
import type { RenderTarget } from '../targets/contracts';
|
|
66
89
|
import type { RenderTargetPhysical } from '../targets/physical';
|
|
67
90
|
import {
|
|
@@ -71,6 +94,7 @@ import {
|
|
|
71
94
|
hasPendingTemporalGpuSubmit,
|
|
72
95
|
retireTemporalGpuState,
|
|
73
96
|
retireTemporalGpuStateAfterFence,
|
|
97
|
+
TEMPORAL_HISTORY_FORMATS,
|
|
74
98
|
temporalReadIndex,
|
|
75
99
|
temporalWriteIndex,
|
|
76
100
|
} from '../temporal/gpu';
|
|
@@ -79,7 +103,12 @@ import type { TransmissionDemand } from '../transmission/projection';
|
|
|
79
103
|
import { hasVolumetricFogCapability } from '../volume/capability';
|
|
80
104
|
import { deriveVolumetricFogExtent, deriveVolumetricFogResolvedExtent } from '../volume/resources';
|
|
81
105
|
import { buildPerFrameBindGroups } from './frame-lighting';
|
|
82
|
-
import {
|
|
106
|
+
import {
|
|
107
|
+
type GraphTargetPassReplayPrefixReceipt,
|
|
108
|
+
type GraphTargetPassReplayReceipt,
|
|
109
|
+
getTextureIdentity,
|
|
110
|
+
type RenderFrameState,
|
|
111
|
+
} from './frame-snapshot';
|
|
83
112
|
import type { GpuPassTimingPassIdentity } from './gpu-pass-timing/contract.js';
|
|
84
113
|
import type { GpuPassTimingCapture, GpuPassTimingSession } from './gpu-pass-timing/session.js';
|
|
85
114
|
import type { GpuTimingCapture } from './gpu-timing';
|
|
@@ -198,13 +227,14 @@ export function commitReflectionFallbackGraph(
|
|
|
198
227
|
function importTemporalHistoryTarget(
|
|
199
228
|
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
200
229
|
label: string,
|
|
201
|
-
kind: 'color' | 'temporal',
|
|
230
|
+
kind: 'color' | 'temporal' | 'stability',
|
|
202
231
|
role: 'read' | 'write',
|
|
203
232
|
): import('../render-pipeline').RenderPipelineTarget {
|
|
233
|
+
const format = TEMPORAL_HISTORY_FORMATS[kind];
|
|
204
234
|
const texture = graph.importTexture(
|
|
205
235
|
label,
|
|
206
236
|
{
|
|
207
|
-
format
|
|
237
|
+
format,
|
|
208
238
|
size: 'surface',
|
|
209
239
|
usage:
|
|
210
240
|
GPU_TEXTURE_USAGE_COPY_SRC |
|
|
@@ -222,7 +252,7 @@ function importTemporalHistoryTarget(
|
|
|
222
252
|
frame.targetH,
|
|
223
253
|
);
|
|
224
254
|
const index = role === 'read' ? temporalReadIndex(state) : temporalWriteIndex(state);
|
|
225
|
-
return
|
|
255
|
+
return state[kind][index].texture;
|
|
226
256
|
},
|
|
227
257
|
);
|
|
228
258
|
if (!texture.ok) throw texture.error;
|
|
@@ -239,11 +269,11 @@ function importTemporalHistoryTarget(
|
|
|
239
269
|
frame.targetH,
|
|
240
270
|
);
|
|
241
271
|
const index = role === 'read' ? temporalReadIndex(state) : temporalWriteIndex(state);
|
|
242
|
-
return
|
|
272
|
+
return state[kind][index].view;
|
|
243
273
|
},
|
|
244
274
|
);
|
|
245
275
|
if (!view.ok) throw view.error;
|
|
246
|
-
return { texture: texture.value, view: view.value, format
|
|
276
|
+
return { texture: texture.value, view: view.value, format, sampleCount: 1 };
|
|
247
277
|
}
|
|
248
278
|
|
|
249
279
|
function importTemporalHistoryTargets(
|
|
@@ -253,6 +283,18 @@ function importTemporalHistoryTargets(
|
|
|
253
283
|
> {
|
|
254
284
|
return {
|
|
255
285
|
currentColor: importTemporalHistoryTarget(graph, 'taa-history-current-color', 'color', 'write'),
|
|
286
|
+
currentStability: importTemporalHistoryTarget(
|
|
287
|
+
graph,
|
|
288
|
+
'taa-history-current-stability',
|
|
289
|
+
'stability',
|
|
290
|
+
'write',
|
|
291
|
+
),
|
|
292
|
+
previousStability: importTemporalHistoryTarget(
|
|
293
|
+
graph,
|
|
294
|
+
'taa-history-previous-stability',
|
|
295
|
+
'stability',
|
|
296
|
+
'read',
|
|
297
|
+
),
|
|
256
298
|
previousColor: importTemporalHistoryTarget(
|
|
257
299
|
graph,
|
|
258
300
|
'taa-history-previous-color',
|
|
@@ -274,6 +316,110 @@ function importTemporalHistoryTargets(
|
|
|
274
316
|
};
|
|
275
317
|
}
|
|
276
318
|
|
|
319
|
+
function importSsrHistoryTarget(
|
|
320
|
+
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
321
|
+
label: string,
|
|
322
|
+
role: 'read' | 'write',
|
|
323
|
+
surface = false,
|
|
324
|
+
): import('../render-pipeline').RenderPipelineTarget {
|
|
325
|
+
const texture = graph.importTexture(
|
|
326
|
+
label,
|
|
327
|
+
{
|
|
328
|
+
format: surface ? 'rgba8unorm' : 'rgba16float',
|
|
329
|
+
size: 'half-surface',
|
|
330
|
+
usage:
|
|
331
|
+
GPU_TEXTURE_USAGE_COPY_SRC |
|
|
332
|
+
GPU_TEXTURE_USAGE_COPY_DST |
|
|
333
|
+
GPU_TEXTURE_USAGE_RENDER_ATTACHMENT |
|
|
334
|
+
GPU_TEXTURE_USAGE_STORAGE_BINDING |
|
|
335
|
+
GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
336
|
+
domain: 'linear-hdr',
|
|
337
|
+
},
|
|
338
|
+
(frame) => {
|
|
339
|
+
const internal = frame as import('./render-context')._InternalRenderPipelineContext;
|
|
340
|
+
const owner = internal.frameState.ssrHistoryOwner;
|
|
341
|
+
const candidate = internal.frameState.ssrHistoryCandidate;
|
|
342
|
+
if (owner === undefined || candidate === undefined) {
|
|
343
|
+
throw new RhiError({
|
|
344
|
+
code: 'rhi-not-available',
|
|
345
|
+
expected: 'SSR history candidate to be staged before graph execution',
|
|
346
|
+
hint: 'begin the SSR history candidate before executing the admitted graph',
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
const slot =
|
|
350
|
+
role === 'read'
|
|
351
|
+
? (candidate.readSlot ?? (candidate.writeSlot === 0 ? 1 : 0))
|
|
352
|
+
: candidate.writeSlot;
|
|
353
|
+
return surface
|
|
354
|
+
? owner.resources.slots[slot].surfaceTexture
|
|
355
|
+
: owner.resources.slots[slot].texture;
|
|
356
|
+
},
|
|
357
|
+
);
|
|
358
|
+
if (!texture.ok) throw texture.error;
|
|
359
|
+
const view = graph.importView(
|
|
360
|
+
texture.value,
|
|
361
|
+
{ label: `${label}.view`, dimension: '2d' },
|
|
362
|
+
(frame) => {
|
|
363
|
+
const internal = frame as import('./render-context')._InternalRenderPipelineContext;
|
|
364
|
+
const owner = internal.frameState.ssrHistoryOwner;
|
|
365
|
+
const candidate = internal.frameState.ssrHistoryCandidate;
|
|
366
|
+
if (owner === undefined || candidate === undefined) {
|
|
367
|
+
throw new RhiError({
|
|
368
|
+
code: 'rhi-not-available',
|
|
369
|
+
expected: 'SSR history candidate to be staged before graph execution',
|
|
370
|
+
hint: 'begin the SSR history candidate before executing the admitted graph',
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
const slot =
|
|
374
|
+
role === 'read'
|
|
375
|
+
? (candidate.readSlot ?? (candidate.writeSlot === 0 ? 1 : 0))
|
|
376
|
+
: candidate.writeSlot;
|
|
377
|
+
return surface ? owner.resources.slots[slot].surfaceView : owner.resources.slots[slot].view;
|
|
378
|
+
},
|
|
379
|
+
);
|
|
380
|
+
if (!view.ok) throw view.error;
|
|
381
|
+
return {
|
|
382
|
+
texture: texture.value,
|
|
383
|
+
view: view.value,
|
|
384
|
+
format: surface ? 'rgba8unorm' : 'rgba16float',
|
|
385
|
+
sampleCount: 1,
|
|
386
|
+
domain: 'linear-hdr',
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function importSsrHistoryTargets(
|
|
391
|
+
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
392
|
+
): NonNullable<
|
|
393
|
+
import('../render-pipeline').RenderPipelineBuildContext<RenderPipelineFrame>['ssrHistory']
|
|
394
|
+
> {
|
|
395
|
+
return {
|
|
396
|
+
previous: importSsrHistoryTarget(graph, 'ssr-history-previous', 'read'),
|
|
397
|
+
output: importSsrHistoryTarget(graph, 'ssr-history-output', 'write'),
|
|
398
|
+
previousSurface: importSsrHistoryTarget(graph, 'ssr-history-previous-surface', 'read', true),
|
|
399
|
+
outputSurface: importSsrHistoryTarget(graph, 'ssr-history-output-surface', 'write', true),
|
|
400
|
+
params: (() => {
|
|
401
|
+
const imported = graph.importBuffer(
|
|
402
|
+
'ssr-history-params',
|
|
403
|
+
{ size: 32, usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST },
|
|
404
|
+
(frame) => {
|
|
405
|
+
const internal = frame as import('./render-context')._InternalRenderPipelineContext;
|
|
406
|
+
const owner = internal.frameState.ssrHistoryOwner;
|
|
407
|
+
if (owner === undefined) {
|
|
408
|
+
throw new RhiError({
|
|
409
|
+
code: 'rhi-not-available',
|
|
410
|
+
expected: 'SSR history owner to be staged before graph execution',
|
|
411
|
+
hint: 'create the renderer-owned SSR history before executing the admitted graph',
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
return owner.resources.paramsBuffer;
|
|
415
|
+
},
|
|
416
|
+
);
|
|
417
|
+
if (!imported.ok) throw imported.error;
|
|
418
|
+
return imported.value;
|
|
419
|
+
})(),
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
277
423
|
export function shouldUseTemporalFrameTransaction(
|
|
278
424
|
antialias: CameraSnapshot['antialias'],
|
|
279
425
|
temporalDemand = false,
|
|
@@ -538,7 +684,6 @@ function addCubeCaptureGraphPasses(
|
|
|
538
684
|
const captureResolveView = captureResolve?.ok ? captureResolve.value : null;
|
|
539
685
|
const captureContext = {
|
|
540
686
|
...internal,
|
|
541
|
-
gpuDrivenEntityKeys: new Set<number>(),
|
|
542
687
|
camera: current().faceCamera,
|
|
543
688
|
// Cube faces are raw scene captures, not display-camera HDR output.
|
|
544
689
|
// Select the PSO against the actual target attachment so an LDR
|
|
@@ -787,6 +932,57 @@ export interface RenderFeatureGraphRuntimeState {
|
|
|
787
932
|
>;
|
|
788
933
|
}
|
|
789
934
|
|
|
935
|
+
/** The exact fields that define one validated feature-plan collection. */
|
|
936
|
+
export interface RenderFeaturePlanRevisionEntry {
|
|
937
|
+
readonly featureIdentity: string;
|
|
938
|
+
readonly generation: number;
|
|
939
|
+
readonly signature: string;
|
|
940
|
+
readonly order: number;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
/** Compact graph-owner state for a completely validated feature-plan set. */
|
|
944
|
+
export interface RenderFeaturePlanRevisionState {
|
|
945
|
+
readonly revision: number;
|
|
946
|
+
readonly entries: readonly RenderFeaturePlanRevisionEntry[];
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
/**
|
|
950
|
+
* Advance the plan revision only when the complete canonical plan collection
|
|
951
|
+
* changes. Equality is an exact field comparison; the canonical signatures
|
|
952
|
+
* have already been recomputed by validation before this helper is called.
|
|
953
|
+
*/
|
|
954
|
+
export function updateRenderFeaturePlanRevision(
|
|
955
|
+
previous: RenderFeaturePlanRevisionState,
|
|
956
|
+
plans: readonly RenderFeaturePlannedFrame[],
|
|
957
|
+
executions: readonly RenderFeaturePlanExecution[],
|
|
958
|
+
): RenderFeaturePlanRevisionState {
|
|
959
|
+
if (
|
|
960
|
+
plans.length === previous.entries.length &&
|
|
961
|
+
plans.every((planned, index) => {
|
|
962
|
+
const prior = previous.entries[index];
|
|
963
|
+
return (
|
|
964
|
+
prior !== undefined &&
|
|
965
|
+
prior.featureIdentity === planned.featureIdentity &&
|
|
966
|
+
prior.generation === planned.generation &&
|
|
967
|
+
prior.signature === planned.signature &&
|
|
968
|
+
prior.order === (executions[index]?.order ?? -1)
|
|
969
|
+
);
|
|
970
|
+
})
|
|
971
|
+
) {
|
|
972
|
+
return previous;
|
|
973
|
+
}
|
|
974
|
+
const entries = plans.map((planned, index) => ({
|
|
975
|
+
featureIdentity: planned.featureIdentity,
|
|
976
|
+
generation: planned.generation,
|
|
977
|
+
signature: planned.signature,
|
|
978
|
+
order: executions[index]?.order ?? -1,
|
|
979
|
+
}));
|
|
980
|
+
return {
|
|
981
|
+
revision: previous.revision + 1,
|
|
982
|
+
entries: Object.freeze(entries),
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
|
|
790
986
|
/** A frame-local graph candidate that is committed only after compilation. */
|
|
791
987
|
export interface RenderFeatureGraphCandidate {
|
|
792
988
|
readonly plans: readonly RenderFeaturePlannedFrame[];
|
|
@@ -795,16 +991,22 @@ export interface RenderFeatureGraphCandidate {
|
|
|
795
991
|
import('../fullscreen-post-process-pass').PostProcessShaderEntry
|
|
796
992
|
>;
|
|
797
993
|
/**
|
|
798
|
-
* Physical
|
|
799
|
-
*
|
|
800
|
-
* signature is unchanged; otherwise queue retirement
|
|
801
|
-
* still referenced by the memoized graph.
|
|
994
|
+
* Physical transient graphics resources are imported into the compiled
|
|
995
|
+
* graph. Their lease therefore needs a new graph even when the declarative
|
|
996
|
+
* plan signature is unchanged; otherwise queue retirement could destroy a
|
|
997
|
+
* buffer still referenced by the memoized graph. Retired GPU-work leases are
|
|
998
|
+
* kept in the completion batch but are not imported by this candidate and do
|
|
999
|
+
* not require a graph revision on their own.
|
|
802
1000
|
*/
|
|
803
1001
|
readonly preparedResourceKey?: string;
|
|
804
1002
|
/** Release candidate-owned prepared resources when graph promotion fails. */
|
|
805
1003
|
readonly onRejected?: () => void;
|
|
806
1004
|
/** Publish candidate-owned runtime declarations only after graph promotion. */
|
|
807
1005
|
readonly onAccepted?: () => void;
|
|
1006
|
+
/** Consume producer frame state only after the command buffer is submitted. */
|
|
1007
|
+
readonly onSubmitted?: () => void;
|
|
1008
|
+
/** Discard producer frame state after graph execution/submission aborts. */
|
|
1009
|
+
readonly onAborted?: () => void;
|
|
808
1010
|
/** Discard candidate-only resources when a base graph is kept as fallback. */
|
|
809
1011
|
readonly onAbandoned?: () => void;
|
|
810
1012
|
}
|
|
@@ -812,6 +1014,139 @@ export interface RenderFeatureGraphCandidate {
|
|
|
812
1014
|
const featureGraphStates = new WeakMap<RenderSystemInternals, RenderFeatureGraphRuntimeState>();
|
|
813
1015
|
const graphDeviceGenerations = new WeakMap<object, number>();
|
|
814
1016
|
|
|
1017
|
+
interface MutableRenderFeatureGraphInspection {
|
|
1018
|
+
planRevisionState: RenderFeaturePlanRevisionState;
|
|
1019
|
+
signatureValidationCalls: number;
|
|
1020
|
+
signatureValidationBytes: number;
|
|
1021
|
+
signatureValidationChars: number;
|
|
1022
|
+
signatureValidationCpuMs: number;
|
|
1023
|
+
signatureValidationCacheHits: number;
|
|
1024
|
+
signatureValidationCacheMisses: number;
|
|
1025
|
+
ensureCalls: number;
|
|
1026
|
+
reuseHits: number;
|
|
1027
|
+
rebuildAttempts: number;
|
|
1028
|
+
compileAttempts: number;
|
|
1029
|
+
compileSuccesses: number;
|
|
1030
|
+
compileFailures: number;
|
|
1031
|
+
validationFailures: number;
|
|
1032
|
+
buildFailures: number;
|
|
1033
|
+
compileCpuMs: number;
|
|
1034
|
+
candidatesWithPreparedBatches: number;
|
|
1035
|
+
preparedKeyChanges: number;
|
|
1036
|
+
accepted: number;
|
|
1037
|
+
rejected: number;
|
|
1038
|
+
abandoned: number;
|
|
1039
|
+
lastPlanSignature: string;
|
|
1040
|
+
lastTopologyKey: string | undefined;
|
|
1041
|
+
lastPreparedResourceKey: string | undefined;
|
|
1042
|
+
preparedKeyObserved: boolean;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
const featureGraphInspections = new WeakMap<
|
|
1046
|
+
RenderSystemInternals,
|
|
1047
|
+
MutableRenderFeatureGraphInspection
|
|
1048
|
+
>();
|
|
1049
|
+
|
|
1050
|
+
function mutableFeatureGraphInspection(
|
|
1051
|
+
internals: RenderSystemInternals,
|
|
1052
|
+
): MutableRenderFeatureGraphInspection {
|
|
1053
|
+
const existing = featureGraphInspections.get(internals);
|
|
1054
|
+
if (existing !== undefined) return existing;
|
|
1055
|
+
const created: MutableRenderFeatureGraphInspection = {
|
|
1056
|
+
planRevisionState: { revision: 0, entries: [] },
|
|
1057
|
+
signatureValidationCalls: 0,
|
|
1058
|
+
signatureValidationBytes: 0,
|
|
1059
|
+
signatureValidationChars: 0,
|
|
1060
|
+
signatureValidationCpuMs: 0,
|
|
1061
|
+
signatureValidationCacheHits: 0,
|
|
1062
|
+
signatureValidationCacheMisses: 0,
|
|
1063
|
+
ensureCalls: 0,
|
|
1064
|
+
reuseHits: 0,
|
|
1065
|
+
rebuildAttempts: 0,
|
|
1066
|
+
compileAttempts: 0,
|
|
1067
|
+
compileSuccesses: 0,
|
|
1068
|
+
compileFailures: 0,
|
|
1069
|
+
validationFailures: 0,
|
|
1070
|
+
buildFailures: 0,
|
|
1071
|
+
compileCpuMs: 0,
|
|
1072
|
+
candidatesWithPreparedBatches: 0,
|
|
1073
|
+
preparedKeyChanges: 0,
|
|
1074
|
+
accepted: 0,
|
|
1075
|
+
rejected: 0,
|
|
1076
|
+
abandoned: 0,
|
|
1077
|
+
lastPlanSignature: '',
|
|
1078
|
+
lastTopologyKey: undefined,
|
|
1079
|
+
lastPreparedResourceKey: undefined,
|
|
1080
|
+
preparedKeyObserved: false,
|
|
1081
|
+
};
|
|
1082
|
+
featureGraphInspections.set(internals, created);
|
|
1083
|
+
return created;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
export function getRenderFeatureGraphInspection(
|
|
1087
|
+
internals: RenderSystemInternals,
|
|
1088
|
+
): RenderFeatureGraphInspection {
|
|
1089
|
+
const metrics = mutableFeatureGraphInspection(internals);
|
|
1090
|
+
return Object.freeze({
|
|
1091
|
+
planRevision: metrics.planRevisionState.revision,
|
|
1092
|
+
signatureValidationCalls: metrics.signatureValidationCalls,
|
|
1093
|
+
signatureValidationBytes: metrics.signatureValidationBytes,
|
|
1094
|
+
signatureValidationChars: metrics.signatureValidationChars,
|
|
1095
|
+
signatureValidationCpuMs: metrics.signatureValidationCpuMs,
|
|
1096
|
+
signatureValidationCacheHits: metrics.signatureValidationCacheHits,
|
|
1097
|
+
signatureValidationCacheMisses: metrics.signatureValidationCacheMisses,
|
|
1098
|
+
ensureCalls: metrics.ensureCalls,
|
|
1099
|
+
reuseHits: metrics.reuseHits,
|
|
1100
|
+
rebuildAttempts: metrics.rebuildAttempts,
|
|
1101
|
+
compileAttempts: metrics.compileAttempts,
|
|
1102
|
+
compileSuccesses: metrics.compileSuccesses,
|
|
1103
|
+
compileFailures: metrics.compileFailures,
|
|
1104
|
+
validationFailures: metrics.validationFailures,
|
|
1105
|
+
buildFailures: metrics.buildFailures,
|
|
1106
|
+
compileCpuMs: metrics.compileCpuMs,
|
|
1107
|
+
candidatesWithPreparedBatches: metrics.candidatesWithPreparedBatches,
|
|
1108
|
+
preparedKeyChanges: metrics.preparedKeyChanges,
|
|
1109
|
+
accepted: metrics.accepted,
|
|
1110
|
+
rejected: metrics.rejected,
|
|
1111
|
+
abandoned: metrics.abandoned,
|
|
1112
|
+
last: Object.freeze({
|
|
1113
|
+
planSignature: metrics.lastPlanSignature,
|
|
1114
|
+
topologyKey: metrics.lastTopologyKey,
|
|
1115
|
+
preparedResourceKey: metrics.lastPreparedResourceKey,
|
|
1116
|
+
}),
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
export function recordRenderFeatureCandidate(
|
|
1121
|
+
internals: RenderSystemInternals,
|
|
1122
|
+
candidate: RenderFeatureGraphCandidate,
|
|
1123
|
+
): void {
|
|
1124
|
+
const metrics = mutableFeatureGraphInspection(internals);
|
|
1125
|
+
if (
|
|
1126
|
+
metrics.preparedKeyObserved &&
|
|
1127
|
+
metrics.lastPreparedResourceKey !== candidate.preparedResourceKey
|
|
1128
|
+
) {
|
|
1129
|
+
metrics.preparedKeyChanges += 1;
|
|
1130
|
+
}
|
|
1131
|
+
metrics.preparedKeyObserved = true;
|
|
1132
|
+
metrics.lastPreparedResourceKey = candidate.preparedResourceKey;
|
|
1133
|
+
if (candidate.preparedResourceKey !== undefined) {
|
|
1134
|
+
metrics.candidatesWithPreparedBatches += 1;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
function recordRenderFeatureCandidateEvent(
|
|
1139
|
+
internals: RenderSystemInternals,
|
|
1140
|
+
candidate: RenderFeatureGraphCandidate,
|
|
1141
|
+
event: 'accepted' | 'rejected' | 'abandoned',
|
|
1142
|
+
): void {
|
|
1143
|
+
const metrics = mutableFeatureGraphInspection(internals);
|
|
1144
|
+
metrics[event] += 1;
|
|
1145
|
+
if (event === 'accepted') candidate.onAccepted?.();
|
|
1146
|
+
else if (event === 'rejected') candidate.onRejected?.();
|
|
1147
|
+
else candidate.onAbandoned?.();
|
|
1148
|
+
}
|
|
1149
|
+
|
|
815
1150
|
interface TimingInstrumentationState {
|
|
816
1151
|
readonly instrumentation: RenderGraphPassInstrumentation<RenderPipelineFrame>;
|
|
817
1152
|
setCapture(capture: GpuPassTimingCapture | undefined): void;
|
|
@@ -830,6 +1165,11 @@ type CompiledGraphTargetAccess = CompiledRenderGraph<RenderPipelineFrame> & {
|
|
|
830
1165
|
readonly getColorTargetTexture: (name: string) => Texture | undefined;
|
|
831
1166
|
};
|
|
832
1167
|
|
|
1168
|
+
type ResolvedDepthPassExecution =
|
|
1169
|
+
import('@forgeax/engine-render-graph').RenderGraphPassExecution & {
|
|
1170
|
+
readonly resolvedDepthStencilAttachmentView?: TextureView;
|
|
1171
|
+
};
|
|
1172
|
+
|
|
833
1173
|
export function getRenderFeatureGraphState(
|
|
834
1174
|
internals: RenderSystemInternals,
|
|
835
1175
|
): RenderFeatureGraphRuntimeState {
|
|
@@ -899,15 +1239,46 @@ export function resolvePostProcessChainAdmission(
|
|
|
899
1239
|
|
|
900
1240
|
function validateRenderFeaturePlans(
|
|
901
1241
|
plans: readonly RenderFeaturePlannedFrame[],
|
|
1242
|
+
metrics?: MutableRenderFeatureGraphInspection,
|
|
902
1243
|
): Result<readonly RenderFeaturePlanExecution[], RenderError> {
|
|
903
1244
|
const identities = new Set<string>();
|
|
904
1245
|
const projected: RenderFeaturePlanExecution[] = [];
|
|
905
1246
|
let previousOrder = -1;
|
|
906
1247
|
for (const [order, planned] of plans.entries()) {
|
|
907
1248
|
const execution = getRenderFeaturePlanExecutionProjection(planned);
|
|
1249
|
+
const signatureMetrics =
|
|
1250
|
+
metrics === undefined ? undefined : { calls: 0, typedArrayBytes: 0, outputChars: 0 };
|
|
1251
|
+
const started =
|
|
1252
|
+
metrics === undefined
|
|
1253
|
+
? 0
|
|
1254
|
+
: typeof performance === 'undefined'
|
|
1255
|
+
? Date.now()
|
|
1256
|
+
: performance.now();
|
|
1257
|
+
// The host records detached structural evidence, but graph admission must
|
|
1258
|
+
// check it again so a mutation between the two synchronous stages cannot
|
|
1259
|
+
// smuggle a stale plan into the compiled graph. Only candidates without
|
|
1260
|
+
// evidence fall back to the canonical serializer.
|
|
1261
|
+
const signatureCacheHit = renderFeaturePlanSignatureEvidenceMatches(
|
|
1262
|
+
planned.plan,
|
|
1263
|
+
planned.signature,
|
|
1264
|
+
);
|
|
1265
|
+
if (metrics !== undefined) {
|
|
1266
|
+
if (signatureCacheHit) metrics.signatureValidationCacheHits += 1;
|
|
1267
|
+
else metrics.signatureValidationCacheMisses += 1;
|
|
1268
|
+
}
|
|
1269
|
+
const recomputedSignature = signatureCacheHit
|
|
1270
|
+
? planned.signature
|
|
1271
|
+
: renderFeaturePlanSignature(planned.plan, signatureMetrics);
|
|
1272
|
+
if (metrics !== undefined) {
|
|
1273
|
+
const now = typeof performance === 'undefined' ? Date.now() : performance.now();
|
|
1274
|
+
metrics.signatureValidationCalls += signatureMetrics?.calls ?? 0;
|
|
1275
|
+
metrics.signatureValidationBytes += signatureMetrics?.typedArrayBytes ?? 0;
|
|
1276
|
+
metrics.signatureValidationChars += signatureMetrics?.outputChars ?? 0;
|
|
1277
|
+
metrics.signatureValidationCpuMs += now - started;
|
|
1278
|
+
}
|
|
908
1279
|
if (
|
|
909
1280
|
identities.has(planned.featureIdentity) ||
|
|
910
|
-
planned.signature !==
|
|
1281
|
+
planned.signature !== recomputedSignature ||
|
|
911
1282
|
execution === undefined ||
|
|
912
1283
|
execution.featureIdentity !== planned.featureIdentity ||
|
|
913
1284
|
execution.order <= previousOrder
|
|
@@ -930,7 +1301,7 @@ function commitFeatureCandidate(
|
|
|
930
1301
|
// Publish renderer-owned declarations only after their device resources have
|
|
931
1302
|
// been admitted. If the acceptance hook throws, the previously accepted
|
|
932
1303
|
// graph/state pair remains visible to the caller.
|
|
933
|
-
candidate
|
|
1304
|
+
recordRenderFeatureCandidateEvent(internals, candidate, 'accepted');
|
|
934
1305
|
const state = getRenderFeatureGraphState(internals);
|
|
935
1306
|
state.plans = candidate.plans;
|
|
936
1307
|
state.fullscreenEffects = candidate.fullscreenEffects;
|
|
@@ -948,10 +1319,12 @@ function topologyOf(
|
|
|
948
1319
|
shadowMapSize: number | undefined,
|
|
949
1320
|
gpuDriven: PreparedGpuDrivenFrame | undefined,
|
|
950
1321
|
featureGraphCandidate: RenderFeatureGraphCandidate | undefined,
|
|
1322
|
+
featurePlanRevision: number,
|
|
951
1323
|
cubeCaptureState: CubeCaptureGraphState | undefined,
|
|
952
1324
|
transmissionDemand: TransmissionDemand | undefined,
|
|
953
1325
|
volumetricFog: ExtractedVolumetricFog | undefined,
|
|
954
1326
|
standardLighting: StandardTopologyInputValue | undefined,
|
|
1327
|
+
ssr: SsrSpatialAdmission | undefined,
|
|
955
1328
|
): Result<RenderPipelineTopology, RhiError> {
|
|
956
1329
|
const cascadeCount = Math.max(1, Math.min(4, Math.round(lights.cascadeCount ?? 1))) as
|
|
957
1330
|
| 1
|
|
@@ -1007,12 +1380,15 @@ function topologyOf(
|
|
|
1007
1380
|
: volumetricFog?.lightKind === undefined
|
|
1008
1381
|
? lights.directional
|
|
1009
1382
|
: undefined;
|
|
1383
|
+
const preparedLut =
|
|
1384
|
+
frameState.pendingStandardLutGpuResources ?? frameState.standardLutGpuResources;
|
|
1010
1385
|
return ok({
|
|
1011
1386
|
pipelineId: STANDARD_PIPELINE_ID,
|
|
1012
1387
|
standardProfile: internals.standardProfile,
|
|
1013
1388
|
config,
|
|
1014
1389
|
clearOnly,
|
|
1015
1390
|
reflectionFallback: { enabled: frameState.reflectionFallbackDemand === true },
|
|
1391
|
+
ssr,
|
|
1016
1392
|
surface: {
|
|
1017
1393
|
width,
|
|
1018
1394
|
height,
|
|
@@ -1025,6 +1401,27 @@ function topologyOf(
|
|
|
1025
1401
|
antialias: camera.antialias,
|
|
1026
1402
|
bloom: camera.bloom,
|
|
1027
1403
|
},
|
|
1404
|
+
atmosphere: !clearOnly && frameState.environmentFrame?.source.kind === 'atmosphere',
|
|
1405
|
+
output: {
|
|
1406
|
+
autoExposure:
|
|
1407
|
+
!clearOnly &&
|
|
1408
|
+
camera.output?.exposure.kind === 'auto' &&
|
|
1409
|
+
(frameState.pendingAutoExposureGpuResources ?? frameState.autoExposureGpuResources) !==
|
|
1410
|
+
undefined,
|
|
1411
|
+
whiteBalance:
|
|
1412
|
+
!clearOnly &&
|
|
1413
|
+
camera.output !== undefined &&
|
|
1414
|
+
(camera.output.temperature !== 6504 || camera.output.tint !== 0),
|
|
1415
|
+
temperature: camera.output?.temperature ?? 6504,
|
|
1416
|
+
tint: camera.output?.tint ?? 0,
|
|
1417
|
+
colorLut:
|
|
1418
|
+
!clearOnly &&
|
|
1419
|
+
(camera.output?.colorLutStrength ?? 0) > 0 &&
|
|
1420
|
+
(frameState.pendingStandardLutGpuResources ?? frameState.standardLutGpuResources) !==
|
|
1421
|
+
undefined,
|
|
1422
|
+
colorLutStrength: camera.output?.colorLutStrength ?? 0,
|
|
1423
|
+
...(preparedLut === undefined ? {} : { lutSourceKey: preparedLut.sourceKey }),
|
|
1424
|
+
},
|
|
1028
1425
|
temporal: {
|
|
1029
1426
|
taa: camera.antialias === 'taa',
|
|
1030
1427
|
motionBlur: isMotionBlurTemporalDemand(camera.motionBlur),
|
|
@@ -1092,9 +1489,7 @@ function topologyOf(
|
|
|
1092
1489
|
maxColorAttachments: internals.device.caps.maxColorAttachments,
|
|
1093
1490
|
},
|
|
1094
1491
|
featureTopologySignature: JSON.stringify({
|
|
1095
|
-
|
|
1096
|
-
featureGraphCandidate?.plans ?? getRenderFeatureGraphState(internals).plans,
|
|
1097
|
-
),
|
|
1492
|
+
planRevision: featurePlanRevision,
|
|
1098
1493
|
fullscreenEffects: featurePostEffectDeclarations,
|
|
1099
1494
|
preparedResourceKey: featureGraphCandidate?.preparedResourceKey ?? '',
|
|
1100
1495
|
cubeCaptureSlots: cubeCaptureState?.work.length ?? 0,
|
|
@@ -1263,7 +1658,9 @@ function resolveTargetBindings(
|
|
|
1263
1658
|
frame.runtime as RenderSystemInternals,
|
|
1264
1659
|
frame.frameState,
|
|
1265
1660
|
frame.pipelineState,
|
|
1266
|
-
|
|
1661
|
+
// This callback is reached only for an actual feature draw. A scene
|
|
1662
|
+
// containing only particles still needs the pipeline's View/light ABI.
|
|
1663
|
+
true,
|
|
1267
1664
|
frame.bindGroupCounts,
|
|
1268
1665
|
{
|
|
1269
1666
|
directionalShadow: frame.frameState.currentDirectionalShadowView ?? undefined,
|
|
@@ -1350,23 +1747,41 @@ export function ensureCompiledFrameGraph(
|
|
|
1350
1747
|
volumeTopologyCandidate = false,
|
|
1351
1748
|
standardLighting?: StandardTopologyInputValue,
|
|
1352
1749
|
onRecoveryError?: (error: unknown) => void,
|
|
1750
|
+
ssr?: SsrSpatialAdmission,
|
|
1353
1751
|
): CompiledRenderGraph<RenderPipelineFrame> | null {
|
|
1752
|
+
const featureMetrics = mutableFeatureGraphInspection(internals);
|
|
1753
|
+
featureMetrics.ensureCalls += 1;
|
|
1354
1754
|
const requestedStandardLightingSignature = standardLightingTopologySignature(standardLighting);
|
|
1355
1755
|
const lastKnownGood = (): CompiledRenderGraph<RenderPipelineFrame> | null =>
|
|
1356
1756
|
frameState.compiledFrameGraph !== null &&
|
|
1757
|
+
!hasSubmissionSensitiveFeatures(getRenderFeatureGraphState(internals).plans) &&
|
|
1357
1758
|
frameState.standardLightingGraphSignature === requestedStandardLightingSignature
|
|
1358
1759
|
? frameState.compiledFrameGraph
|
|
1359
1760
|
: null;
|
|
1360
1761
|
const surfaceWidth = Math.max(1, width);
|
|
1361
1762
|
const surfaceHeight = Math.max(1, height);
|
|
1362
1763
|
const featurePlans = featureGraphCandidate?.plans ?? getRenderFeatureGraphState(internals).plans;
|
|
1363
|
-
const projectedFeaturePlans = validateRenderFeaturePlans(featurePlans);
|
|
1764
|
+
const projectedFeaturePlans = validateRenderFeaturePlans(featurePlans, featureMetrics);
|
|
1364
1765
|
if (!projectedFeaturePlans.ok) {
|
|
1766
|
+
featureMetrics.validationFailures += 1;
|
|
1365
1767
|
onRecoveryError?.(projectedFeaturePlans.error);
|
|
1366
1768
|
reportRenderFeatureGraphError(internals, projectedFeaturePlans.error);
|
|
1367
|
-
featureGraphCandidate
|
|
1769
|
+
if (featureGraphCandidate !== undefined) {
|
|
1770
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
1771
|
+
}
|
|
1368
1772
|
return volumeTopologyCandidate ? null : lastKnownGood();
|
|
1369
1773
|
}
|
|
1774
|
+
const nextPlanRevision = updateRenderFeaturePlanRevision(
|
|
1775
|
+
featureMetrics.planRevisionState,
|
|
1776
|
+
featurePlans,
|
|
1777
|
+
projectedFeaturePlans.value,
|
|
1778
|
+
);
|
|
1779
|
+
if (nextPlanRevision !== featureMetrics.planRevisionState) {
|
|
1780
|
+
featureMetrics.lastPlanSignature = nextPlanRevision.entries
|
|
1781
|
+
.map((entry) => `${entry.featureIdentity}:${entry.signature}`)
|
|
1782
|
+
.join('|');
|
|
1783
|
+
featureMetrics.planRevisionState = nextPlanRevision;
|
|
1784
|
+
}
|
|
1370
1785
|
const topologyResult = topologyOf(
|
|
1371
1786
|
internals,
|
|
1372
1787
|
frameState,
|
|
@@ -1379,15 +1794,20 @@ export function ensureCompiledFrameGraph(
|
|
|
1379
1794
|
shadowMapSize,
|
|
1380
1795
|
gpuDriven,
|
|
1381
1796
|
featureGraphCandidate,
|
|
1797
|
+
featureMetrics.planRevisionState.revision,
|
|
1382
1798
|
cubeCaptureState,
|
|
1383
1799
|
transmissionDemand,
|
|
1384
1800
|
volumetricFog,
|
|
1385
1801
|
standardLighting,
|
|
1802
|
+
ssr,
|
|
1386
1803
|
);
|
|
1387
1804
|
if (!topologyResult.ok) {
|
|
1805
|
+
featureMetrics.buildFailures += 1;
|
|
1388
1806
|
onRecoveryError?.(topologyResult.error);
|
|
1389
1807
|
internals.errorRegistry.fire(topologyResult.error);
|
|
1390
|
-
featureGraphCandidate
|
|
1808
|
+
if (featureGraphCandidate !== undefined) {
|
|
1809
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
1810
|
+
}
|
|
1391
1811
|
return volumeTopologyCandidate ? null : lastKnownGood();
|
|
1392
1812
|
}
|
|
1393
1813
|
const requestedPostEffects = topologyResult.value.config?.postEffects ?? [];
|
|
@@ -1416,7 +1836,7 @@ export function ensureCompiledFrameGraph(
|
|
|
1416
1836
|
getPipeline(
|
|
1417
1837
|
identity,
|
|
1418
1838
|
built.bindGroupLayout,
|
|
1419
|
-
topologyResult.value.surface.storageFormat as GPUTextureFormat,
|
|
1839
|
+
[topologyResult.value.surface.storageFormat as GPUTextureFormat],
|
|
1420
1840
|
entry,
|
|
1421
1841
|
) !== null
|
|
1422
1842
|
);
|
|
@@ -1427,7 +1847,9 @@ export function ensureCompiledFrameGraph(
|
|
|
1427
1847
|
// Do not publish a candidate whose fullscreen chain is only partially
|
|
1428
1848
|
// ready. Keep the accepted graph (including its prior post-effect chain)
|
|
1429
1849
|
// and retry the same feature candidate on the next frame.
|
|
1430
|
-
featureGraphCandidate
|
|
1850
|
+
if (featureGraphCandidate !== undefined) {
|
|
1851
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
1852
|
+
}
|
|
1431
1853
|
return acceptedLkg;
|
|
1432
1854
|
}
|
|
1433
1855
|
const topology = postProcessAdmission.pending
|
|
@@ -1441,6 +1863,12 @@ export function ensureCompiledFrameGraph(
|
|
|
1441
1863
|
: topologyResult.value;
|
|
1442
1864
|
const key = JSON.stringify({
|
|
1443
1865
|
topology,
|
|
1866
|
+
// Observation domains are an explicit per-frame graph demand. They are
|
|
1867
|
+
// part of the cache identity so a request made after the ordinary graph
|
|
1868
|
+
// was compiled can admit the matching tone/output capture boundaries on
|
|
1869
|
+
// that receipt without forcing every unobserved frame onto the split
|
|
1870
|
+
// output path.
|
|
1871
|
+
observationCaptureDomains: [...(internals.observationCaptureDomains ?? [])].sort(),
|
|
1444
1872
|
// GPU-driven residency can become available after the first record pass
|
|
1445
1873
|
// (custom mesh handles are resolved into the per-frame projection). The
|
|
1446
1874
|
// topology signature alone is intentionally stable across that lifecycle,
|
|
@@ -1461,11 +1889,13 @@ export function ensureCompiledFrameGraph(
|
|
|
1461
1889
|
]),
|
|
1462
1890
|
});
|
|
1463
1891
|
if (frameState.compiledFrameGraph !== null && frameState.compiledFrameGraphTopologyKey === key) {
|
|
1892
|
+
featureMetrics.reuseHits += 1;
|
|
1893
|
+
featureMetrics.lastTopologyKey = key;
|
|
1464
1894
|
frameState.standardLightingGraphSignature = requestedStandardLightingSignature;
|
|
1465
1895
|
if (featureGraphCandidate !== undefined && !postProcessAdmission.pending) {
|
|
1466
1896
|
commitFeatureCandidate(internals, featureGraphCandidate);
|
|
1467
1897
|
} else if (featureGraphCandidate !== undefined) {
|
|
1468
|
-
featureGraphCandidate
|
|
1898
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'abandoned');
|
|
1469
1899
|
}
|
|
1470
1900
|
// A candidate flag only describes a possible topology replacement. When
|
|
1471
1901
|
// the derived key is unchanged there is no replacement to stage: reuse the
|
|
@@ -1474,17 +1904,109 @@ export function ensureCompiledFrameGraph(
|
|
|
1474
1904
|
return frameState.compiledFrameGraph;
|
|
1475
1905
|
}
|
|
1476
1906
|
|
|
1907
|
+
featureMetrics.rebuildAttempts += 1;
|
|
1908
|
+
featureMetrics.lastTopologyKey = key;
|
|
1909
|
+
const discardPendingStandardOutput = (): void => {
|
|
1910
|
+
if (frameState.pendingAutoExposureGpuResources !== undefined) {
|
|
1911
|
+
retireAutoExposureGpuResources(frameState.pendingAutoExposureGpuResources);
|
|
1912
|
+
frameState.pendingAutoExposureGpuResources = undefined;
|
|
1913
|
+
}
|
|
1914
|
+
if (frameState.pendingStandardLutGpuResources !== undefined) {
|
|
1915
|
+
retireStandardLutGpuResources(frameState.pendingStandardLutGpuResources);
|
|
1916
|
+
frameState.pendingStandardLutGpuResources = undefined;
|
|
1917
|
+
}
|
|
1918
|
+
};
|
|
1477
1919
|
const builder = new RenderGraphBuilder<RenderPipelineFrame>();
|
|
1920
|
+
const autoExposureResources =
|
|
1921
|
+
topology.output?.autoExposure === true ? importAutoExposureGraphResources(builder) : undefined;
|
|
1922
|
+
if (autoExposureResources !== undefined && !autoExposureResources.ok) {
|
|
1923
|
+
internals.errorRegistry.fire(autoExposureResources.error);
|
|
1924
|
+
featureGraphCandidate?.onRejected?.();
|
|
1925
|
+
discardPendingStandardOutput();
|
|
1926
|
+
return lastKnownGood();
|
|
1927
|
+
}
|
|
1928
|
+
const lutResources =
|
|
1929
|
+
topology.output?.colorLut === true
|
|
1930
|
+
? (() => {
|
|
1931
|
+
const prepared =
|
|
1932
|
+
frameState.pendingStandardLutGpuResources ?? frameState.standardLutGpuResources;
|
|
1933
|
+
if (prepared === undefined) return undefined;
|
|
1934
|
+
const texture = builder.importTexture(
|
|
1935
|
+
'standard-color-lut-source',
|
|
1936
|
+
{
|
|
1937
|
+
format: 'rgba16float',
|
|
1938
|
+
size: {
|
|
1939
|
+
width: prepared.size,
|
|
1940
|
+
height: prepared.size,
|
|
1941
|
+
depthOrArrayLayers: prepared.size,
|
|
1942
|
+
},
|
|
1943
|
+
dimension: '3d',
|
|
1944
|
+
usage: GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
1945
|
+
},
|
|
1946
|
+
(frame) =>
|
|
1947
|
+
(
|
|
1948
|
+
(frame as _InternalRenderPipelineContext).frameState
|
|
1949
|
+
.pendingStandardLutGpuResources ??
|
|
1950
|
+
(frame as _InternalRenderPipelineContext).frameState.standardLutGpuResources
|
|
1951
|
+
)?.texture ?? prepared.texture,
|
|
1952
|
+
);
|
|
1953
|
+
if (!texture.ok) return texture;
|
|
1954
|
+
const view = builder.importView(
|
|
1955
|
+
texture.value,
|
|
1956
|
+
{ label: 'standard-color-lut-source.view', dimension: '3d' },
|
|
1957
|
+
(frame) =>
|
|
1958
|
+
(
|
|
1959
|
+
(frame as _InternalRenderPipelineContext).frameState
|
|
1960
|
+
.pendingStandardLutGpuResources ??
|
|
1961
|
+
(frame as _InternalRenderPipelineContext).frameState.standardLutGpuResources
|
|
1962
|
+
)?.view ?? prepared.view,
|
|
1963
|
+
);
|
|
1964
|
+
if (!view.ok) return view;
|
|
1965
|
+
return ok({ texture: texture.value, view: view.value, prepared });
|
|
1966
|
+
})()
|
|
1967
|
+
: undefined;
|
|
1968
|
+
if (lutResources !== undefined && !lutResources.ok) {
|
|
1969
|
+
internals.errorRegistry.fire(lutResources.error);
|
|
1970
|
+
featureGraphCandidate?.onRejected?.();
|
|
1971
|
+
discardPendingStandardOutput();
|
|
1972
|
+
return lastKnownGood();
|
|
1973
|
+
}
|
|
1478
1974
|
const taaHistory = camera.antialias === 'taa' ? importTemporalHistoryTargets(builder) : undefined;
|
|
1975
|
+
const ssrHistory = ssr?.status === 'admitted' ? importSsrHistoryTargets(builder) : undefined;
|
|
1479
1976
|
let projectedFeatures = false;
|
|
1977
|
+
const featureProjection = createRenderFeatureProjectionState();
|
|
1978
|
+
let featureShadows:
|
|
1979
|
+
| ReturnType<typeof projectRenderFeatureShadows<RenderPipelineFrame>>
|
|
1980
|
+
| undefined;
|
|
1480
1981
|
let projectedGpuDriven = false;
|
|
1481
1982
|
const built = frameState.activePipeline.build(
|
|
1482
1983
|
{
|
|
1483
1984
|
graph: builder,
|
|
1985
|
+
observationCaptureDomains: internals.observationCaptureDomains,
|
|
1986
|
+
...(autoExposureResources?.ok === true
|
|
1987
|
+
? { standardOutput: { autoExposure: autoExposureResources.value } }
|
|
1988
|
+
: {}),
|
|
1989
|
+
...(lutResources?.ok === true
|
|
1990
|
+
? {
|
|
1991
|
+
standardOutput: {
|
|
1992
|
+
...(autoExposureResources?.ok === true
|
|
1993
|
+
? { autoExposure: autoExposureResources.value }
|
|
1994
|
+
: {}),
|
|
1995
|
+
colorLut: {
|
|
1996
|
+
view: lutResources.value.view,
|
|
1997
|
+
sampler: lutResources.value.prepared.sampler,
|
|
1998
|
+
strength: lutResources.value.prepared.strength,
|
|
1999
|
+
bindGroupLayout: lutResources.value.prepared.bindGroupLayout,
|
|
2000
|
+
bindGroup: lutResources.value.prepared.bindGroup,
|
|
2001
|
+
},
|
|
2002
|
+
},
|
|
2003
|
+
}
|
|
2004
|
+
: {}),
|
|
1484
2005
|
...(standardLighting === undefined ? {} : { standardLighting }),
|
|
1485
2006
|
capabilities: { rgba16floatRenderable: internals.device.caps.rgba16floatRenderable },
|
|
1486
2007
|
...(occlusion === undefined ? {} : { occlusion }),
|
|
1487
2008
|
...(taaHistory === undefined ? {} : { taaHistory }),
|
|
2009
|
+
...(ssrHistory === undefined ? {} : { ssrHistory }),
|
|
1488
2010
|
encodeTransmissionMip: ({ pass, resources, source }) => {
|
|
1489
2011
|
const sourceView = resources.textureView(source);
|
|
1490
2012
|
if (!sourceView.ok) throw sourceView.error;
|
|
@@ -1496,14 +2018,53 @@ export function ensureCompiledFrameGraph(
|
|
|
1496
2018
|
projectedGpuDriven = true;
|
|
1497
2019
|
return gpuDriven.project(builder, target.format, target.sampleCount);
|
|
1498
2020
|
},
|
|
1499
|
-
|
|
2021
|
+
...(gpuDriven?.projectShadow === undefined
|
|
2022
|
+
? {}
|
|
2023
|
+
: {
|
|
2024
|
+
projectGpuDrivenShadow: (identity) =>
|
|
2025
|
+
gpuDriven.projectShadow?.(builder, identity) ?? ok(undefined),
|
|
2026
|
+
}),
|
|
2027
|
+
contributeShadowFeatures: () =>
|
|
2028
|
+
(featureShadows ??= projectRenderFeatureShadows(
|
|
2029
|
+
builder,
|
|
2030
|
+
projectedFeaturePlans.value,
|
|
2031
|
+
featureProjection,
|
|
2032
|
+
)),
|
|
2033
|
+
contributeFeatures: (
|
|
2034
|
+
targets,
|
|
2035
|
+
semanticTargets = [],
|
|
2036
|
+
namedTargets = {},
|
|
2037
|
+
standardSurfaceAccesses = [],
|
|
2038
|
+
) => {
|
|
1500
2039
|
if (projectedFeatures) return ok(undefined);
|
|
1501
2040
|
projectedFeatures = true;
|
|
1502
2041
|
if (projectedFeaturePlans.value.length === 0) return ok(undefined);
|
|
1503
2042
|
const resolveTarget = targetResolver(targets, semanticTargets, namedTargets);
|
|
1504
2043
|
const projected = projectPlanExecutions(builder, projectedFeaturePlans.value, {
|
|
2044
|
+
state: featureProjection,
|
|
1505
2045
|
resolveTarget,
|
|
2046
|
+
standardSurfaceAccesses,
|
|
1506
2047
|
resolveBindings: (input) => resolveTargetBindings(input, featurePostProcessEntries),
|
|
2048
|
+
resolveStandardLighting: (frame, pipeline) => {
|
|
2049
|
+
const context = frame as import('./render-context')._InternalRenderPipelineContext;
|
|
2050
|
+
if (context.standardLighting?.kind !== 'clustered') return undefined;
|
|
2051
|
+
const layout = (
|
|
2052
|
+
pipeline as RenderPipeline & {
|
|
2053
|
+
getBindGroupLayout?: (index: number) => BindGroupLayout;
|
|
2054
|
+
}
|
|
2055
|
+
).getBindGroupLayout?.(2);
|
|
2056
|
+
if (layout === undefined) return undefined;
|
|
2057
|
+
return (
|
|
2058
|
+
createStandardSurfaceLightingBindGroup(
|
|
2059
|
+
context.runtime,
|
|
2060
|
+
layout,
|
|
2061
|
+
context.standardLighting.prepared.layout.grid,
|
|
2062
|
+
context.hdrpSsaoBlurredView === undefined
|
|
2063
|
+
? { enabled: false }
|
|
2064
|
+
: { enabled: true, ssaoBlurredView: context.hdrpSsaoBlurredView },
|
|
2065
|
+
) ?? undefined
|
|
2066
|
+
);
|
|
2067
|
+
},
|
|
1507
2068
|
reportError: (error) => reportRenderFeatureGraphError(internals, error),
|
|
1508
2069
|
});
|
|
1509
2070
|
return projected.ok ? ok(undefined) : projected;
|
|
@@ -1524,19 +2085,33 @@ export function ensureCompiledFrameGraph(
|
|
|
1524
2085
|
topology,
|
|
1525
2086
|
);
|
|
1526
2087
|
if (!built.ok) {
|
|
2088
|
+
featureMetrics.buildFailures += 1;
|
|
1527
2089
|
onRecoveryError?.(built.error);
|
|
1528
2090
|
internals.errorRegistry.fire(built.error);
|
|
1529
2091
|
featureGraphCandidate?.onRejected?.();
|
|
2092
|
+
discardPendingStandardOutput();
|
|
2093
|
+
if (featureGraphCandidate !== undefined) {
|
|
2094
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
2095
|
+
}
|
|
1530
2096
|
return volumeTopologyCandidate ? null : lastKnownGood();
|
|
1531
2097
|
}
|
|
2098
|
+
featureMetrics.compileAttempts += 1;
|
|
2099
|
+
const compileStarted = typeof performance === 'undefined' ? Date.now() : performance.now();
|
|
1532
2100
|
const compiled = builder.compile({
|
|
1533
2101
|
device: internals.device,
|
|
1534
2102
|
surfaceSize: { width: surfaceWidth, height: surfaceHeight },
|
|
1535
2103
|
});
|
|
2104
|
+
featureMetrics.compileCpuMs +=
|
|
2105
|
+
(typeof performance === 'undefined' ? Date.now() : performance.now()) - compileStarted;
|
|
1536
2106
|
if (!compiled.ok) {
|
|
2107
|
+
featureMetrics.compileFailures += 1;
|
|
1537
2108
|
onRecoveryError?.(compiled.error);
|
|
1538
2109
|
internals.errorRegistry.fire(compiled.error);
|
|
1539
2110
|
featureGraphCandidate?.onRejected?.();
|
|
2111
|
+
discardPendingStandardOutput();
|
|
2112
|
+
if (featureGraphCandidate !== undefined) {
|
|
2113
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
2114
|
+
}
|
|
1540
2115
|
return lastKnownGood();
|
|
1541
2116
|
}
|
|
1542
2117
|
const previous = frameState.compiledFrameGraph;
|
|
@@ -1551,21 +2126,31 @@ export function ensureCompiledFrameGraph(
|
|
|
1551
2126
|
frameState.compiledFrameGraphGeneration += 1;
|
|
1552
2127
|
const compiledTargets = compiled.value as CompiledGraphTargetAccess;
|
|
1553
2128
|
frameState.graphGeneration += 1;
|
|
2129
|
+
featureMetrics.compileSuccesses += 1;
|
|
1554
2130
|
frameState.perFrameGraph = {
|
|
1555
2131
|
getColorTargetDescriptor: (name) => compiledTargets.getColorTargetDescriptor(name),
|
|
1556
2132
|
getColorTargetView: (name) => compiledTargets.getColorTargetView(name),
|
|
1557
2133
|
getColorTargetTexture: (name) => compiledTargets.getColorTargetTexture(name),
|
|
1558
2134
|
graphGeneration: frameState.graphGeneration,
|
|
1559
2135
|
};
|
|
2136
|
+
// View buffer replacement is safe to retire once the compiled graph owns
|
|
2137
|
+
// the new imports. Shadow cache publication remains submit-transactional
|
|
2138
|
+
// and is committed only by executeCompiledFrameGraph's onSubmitted hook.
|
|
2139
|
+
if (gpuDriven?._commitGpuResourceReplacement !== undefined) {
|
|
2140
|
+
gpuDriven._commitGpuResourceReplacement();
|
|
2141
|
+
} else {
|
|
2142
|
+
// Synthetic/internal prepared projections predating the split own no
|
|
2143
|
+
// shadow cache; retain their original graph-promotion callback.
|
|
2144
|
+
gpuDriven?._commitResourceReplacement();
|
|
2145
|
+
}
|
|
1560
2146
|
const deviceGeneration = internals.deviceScope?.generation;
|
|
1561
2147
|
if (deviceGeneration !== undefined) {
|
|
1562
2148
|
graphDeviceGenerations.set(compiled.value, deviceGeneration);
|
|
1563
2149
|
}
|
|
1564
|
-
gpuDriven?._commitResourceReplacement();
|
|
1565
2150
|
if (featureGraphCandidate !== undefined && !postProcessAdmission.pending) {
|
|
1566
2151
|
commitFeatureCandidate(internals, featureGraphCandidate);
|
|
1567
2152
|
} else if (featureGraphCandidate !== undefined) {
|
|
1568
|
-
featureGraphCandidate
|
|
2153
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'abandoned');
|
|
1569
2154
|
}
|
|
1570
2155
|
if (!volumeTopologyCandidate && previous !== null) retire(frameState, previous);
|
|
1571
2156
|
return compiled.value;
|
|
@@ -1577,15 +2162,21 @@ export function executeCompiledFrameGraph(
|
|
|
1577
2162
|
frame: RenderPipelineFrame,
|
|
1578
2163
|
encoder: RhiCommandEncoder,
|
|
1579
2164
|
runPass?: import('@forgeax/engine-render-graph').RenderGraphPassRunner,
|
|
1580
|
-
frameHooks?:
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
2165
|
+
frameHooks?:
|
|
2166
|
+
| {
|
|
2167
|
+
readonly afterGraphExecute?: () => Result<void, RhiError>;
|
|
2168
|
+
readonly onSubmitted?: () => void;
|
|
2169
|
+
readonly onAborted?: () => void;
|
|
2170
|
+
}
|
|
2171
|
+
// Keep the pre-submit-hook shape accepted for internal callers that have
|
|
2172
|
+
// not yet migrated to the typed frame hooks object.
|
|
2173
|
+
| (() => void),
|
|
1585
2174
|
readbackFaces?: readonly number[],
|
|
1586
2175
|
onSubmitted?: (completed: Promise<unknown>) => void,
|
|
1587
2176
|
timingCapture?: GpuTimingCapture,
|
|
1588
2177
|
): boolean {
|
|
2178
|
+
const legacySubmitCommit = typeof frameHooks === 'function' ? frameHooks : undefined;
|
|
2179
|
+
const resolvedFrameHooks = typeof frameHooks === 'function' ? undefined : frameHooks;
|
|
1589
2180
|
const graph = frameState.compiledFrameGraph;
|
|
1590
2181
|
const rejectTemporalFrame = (): void => {
|
|
1591
2182
|
if (frameState.temporalFrameInput === undefined) return;
|
|
@@ -1594,6 +2185,8 @@ export function executeCompiledFrameGraph(
|
|
|
1594
2185
|
};
|
|
1595
2186
|
if (graph === null) {
|
|
1596
2187
|
timingCapture?.discard();
|
|
2188
|
+
frameState.pendingAutoExposureState = undefined;
|
|
2189
|
+
frameState.pendingStandardLutState = undefined;
|
|
1597
2190
|
settleVolumetricFogGraphCandidate(frameState, false);
|
|
1598
2191
|
rejectTemporalFrame();
|
|
1599
2192
|
return false;
|
|
@@ -1664,14 +2257,327 @@ export function executeCompiledFrameGraph(
|
|
|
1664
2257
|
const transaction = executeRendererFrameTransaction<PreparedCommand>({
|
|
1665
2258
|
build: () => ({ ok: true, value: { command: undefined as never } }),
|
|
1666
2259
|
execute: () => {
|
|
1667
|
-
const
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
2260
|
+
const graphCapture = frameState.graphTargetCapture;
|
|
2261
|
+
const replayPassNames = graphCapture?.replayPassNames;
|
|
2262
|
+
const unsupportedCaptureKind =
|
|
2263
|
+
graphCapture !== undefined &&
|
|
2264
|
+
graphCapture.kind !== undefined &&
|
|
2265
|
+
graphCapture.kind !== 'target-copy' &&
|
|
2266
|
+
graphCapture.kind !== 'pass-replay';
|
|
2267
|
+
if (unsupportedCaptureKind || replayPassNames !== undefined) {
|
|
2268
|
+
if (graphCapture === undefined) {
|
|
2269
|
+
return { ok: false, stage: 'execute' };
|
|
2270
|
+
}
|
|
2271
|
+
const passNames = graph.inspect().passes.map((pass) => pass.name);
|
|
2272
|
+
const passNameCounts = new Map<string, number>();
|
|
2273
|
+
for (const passName of passNames) {
|
|
2274
|
+
passNameCounts.set(passName, (passNameCounts.get(passName) ?? 0) + 1);
|
|
2275
|
+
}
|
|
2276
|
+
const passNameSet = new Set(passNames);
|
|
2277
|
+
const selectedReplayPassNames = replayPassNames ?? [];
|
|
2278
|
+
const requestedPassNames = new Set(selectedReplayPassNames);
|
|
2279
|
+
const passReplayCapture = graphCapture.kind === 'pass-replay' ? graphCapture : undefined;
|
|
2280
|
+
const onPassEncoded = passReplayCapture?.onPassEncoded;
|
|
2281
|
+
const onPrefixEncoded = passReplayCapture?.onPrefixEncoded;
|
|
2282
|
+
const depthAttachmentPassName = passReplayCapture?.depthAttachmentPassName;
|
|
2283
|
+
const observeAfterPassName = passReplayCapture?.observeAfterPassName;
|
|
2284
|
+
let replayValidationFailed = false;
|
|
2285
|
+
const duplicatePassName = selectedReplayPassNames.find(
|
|
2286
|
+
(passName, index) => selectedReplayPassNames.indexOf(passName) !== index,
|
|
2287
|
+
);
|
|
2288
|
+
const invalidPassName = selectedReplayPassNames.find(
|
|
2289
|
+
(passName) => !passNameSet.has(passName),
|
|
2290
|
+
);
|
|
2291
|
+
const nonUniquePassName = selectedReplayPassNames.find(
|
|
2292
|
+
(passName) => passNameCounts.get(passName) !== 1,
|
|
2293
|
+
);
|
|
2294
|
+
const replayFailure = (reason: string): void => {
|
|
2295
|
+
replayValidationFailed = true;
|
|
2296
|
+
internals.errorRegistry.fire(
|
|
2297
|
+
new RhiError({
|
|
2298
|
+
code: 'webgpu-runtime-error',
|
|
2299
|
+
expected:
|
|
2300
|
+
'the requested graph target replay pass selection is valid and executes once',
|
|
2301
|
+
hint: 'inspect replayPassNames against the compiled graph pass roster',
|
|
2302
|
+
detail: {
|
|
2303
|
+
error: {
|
|
2304
|
+
code: 'graph-target-capture-failed',
|
|
2305
|
+
message: JSON.stringify({
|
|
2306
|
+
target: graphCapture.kind === 'pass-replay' ? undefined : graphCapture.name,
|
|
2307
|
+
replayPassNames,
|
|
2308
|
+
availablePassNames: passNames,
|
|
2309
|
+
reason,
|
|
2310
|
+
}),
|
|
2311
|
+
},
|
|
2312
|
+
},
|
|
2313
|
+
}),
|
|
2314
|
+
);
|
|
2315
|
+
};
|
|
2316
|
+
if (unsupportedCaptureKind) {
|
|
2317
|
+
replayFailure('capture-kind-unknown');
|
|
2318
|
+
return { ok: false, stage: 'execute' };
|
|
2319
|
+
}
|
|
2320
|
+
if (replayPassNames === undefined) {
|
|
2321
|
+
replayFailure('replay-pass-selection-missing');
|
|
2322
|
+
return { ok: false, stage: 'execute' };
|
|
2323
|
+
}
|
|
2324
|
+
if (replayPassNames.length === 0) {
|
|
2325
|
+
replayFailure('replay-pass-selection-empty');
|
|
2326
|
+
return { ok: false, stage: 'execute' };
|
|
2327
|
+
}
|
|
2328
|
+
if (duplicatePassName !== undefined) {
|
|
2329
|
+
replayFailure(`replay-pass-selection-duplicate:${duplicatePassName}`);
|
|
2330
|
+
return { ok: false, stage: 'execute' };
|
|
2331
|
+
}
|
|
2332
|
+
if (invalidPassName !== undefined) {
|
|
2333
|
+
replayFailure(`replay-pass-selection-unknown:${invalidPassName}`);
|
|
2334
|
+
return { ok: false, stage: 'execute' };
|
|
2335
|
+
}
|
|
2336
|
+
if (nonUniquePassName !== undefined) {
|
|
2337
|
+
replayFailure(`replay-pass-selection-non-unique:${nonUniquePassName}`);
|
|
2338
|
+
return { ok: false, stage: 'execute' };
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
if (onPrefixEncoded !== undefined) {
|
|
2342
|
+
if (onPassEncoded !== undefined) {
|
|
2343
|
+
replayFailure('pass-replay-prefix-callback-conflict');
|
|
2344
|
+
return { ok: false, stage: 'execute' };
|
|
2345
|
+
}
|
|
2346
|
+
if (depthAttachmentPassName === undefined) {
|
|
2347
|
+
replayFailure('pass-replay-depth-attachment-name-missing');
|
|
2348
|
+
return { ok: false, stage: 'execute' };
|
|
2349
|
+
}
|
|
2350
|
+
if (observeAfterPassName === undefined) {
|
|
2351
|
+
replayFailure('pass-replay-observe-boundary-name-missing');
|
|
2352
|
+
return { ok: false, stage: 'execute' };
|
|
2353
|
+
}
|
|
2354
|
+
const firstNonPrefixPass = selectedReplayPassNames.find(
|
|
2355
|
+
(passName, index) => passName !== passNames[index],
|
|
2356
|
+
);
|
|
2357
|
+
if (
|
|
2358
|
+
firstNonPrefixPass !== undefined ||
|
|
2359
|
+
selectedReplayPassNames.length > passNames.length
|
|
2360
|
+
) {
|
|
2361
|
+
replayFailure('pass-replay-selection-not-prefix');
|
|
2362
|
+
return { ok: false, stage: 'execute' };
|
|
2363
|
+
}
|
|
2364
|
+
if (selectedReplayPassNames.at(-1) !== observeAfterPassName) {
|
|
2365
|
+
replayFailure('pass-replay-observe-boundary-not-last');
|
|
2366
|
+
return { ok: false, stage: 'execute' };
|
|
2367
|
+
}
|
|
2368
|
+
const anchorIndex = selectedReplayPassNames.indexOf(depthAttachmentPassName);
|
|
2369
|
+
if (anchorIndex < 0 || anchorIndex > selectedReplayPassNames.length - 1) {
|
|
2370
|
+
replayFailure('pass-replay-depth-attachment-not-in-prefix');
|
|
2371
|
+
return { ok: false, stage: 'execute' };
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2375
|
+
let replayTarget:
|
|
2376
|
+
| {
|
|
2377
|
+
readonly name: string;
|
|
2378
|
+
readonly view: TextureView;
|
|
2379
|
+
readonly texture: Texture;
|
|
2380
|
+
readonly textureIdentity: number;
|
|
2381
|
+
readonly graphGeneration: number;
|
|
2382
|
+
}
|
|
2383
|
+
| undefined;
|
|
2384
|
+
if (onPassEncoded !== undefined || onPrefixEncoded !== undefined) {
|
|
2385
|
+
const targetName = passReplayCapture?.targetName;
|
|
2386
|
+
const graphAccess = frameState.perFrameGraph;
|
|
2387
|
+
const targetView =
|
|
2388
|
+
targetName === undefined ? undefined : graphAccess?.getColorTargetView(targetName);
|
|
2389
|
+
const targetTexture =
|
|
2390
|
+
targetName === undefined ? undefined : graphAccess?.getColorTargetTexture(targetName);
|
|
2391
|
+
const targetDescriptor =
|
|
2392
|
+
targetName === undefined
|
|
2393
|
+
? undefined
|
|
2394
|
+
: graphAccess?.getColorTargetDescriptor(targetName);
|
|
2395
|
+
if (targetName === undefined) {
|
|
2396
|
+
replayFailure('pass-replay-target-name-missing');
|
|
2397
|
+
return { ok: false, stage: 'execute' };
|
|
2398
|
+
}
|
|
2399
|
+
if (graphAccess === undefined || graphAccess === null) {
|
|
2400
|
+
replayFailure(`pass-replay-target-missing:${targetName}`);
|
|
2401
|
+
return { ok: false, stage: 'execute' };
|
|
2402
|
+
}
|
|
2403
|
+
if (targetView === undefined || targetTexture === undefined) {
|
|
2404
|
+
replayFailure(`pass-replay-target-missing:${targetName}`);
|
|
2405
|
+
return { ok: false, stage: 'execute' };
|
|
2406
|
+
}
|
|
2407
|
+
if (targetDescriptor !== undefined && targetDescriptor.texture !== targetTexture) {
|
|
2408
|
+
replayFailure(`pass-replay-target-identity-mismatch:${targetName}`);
|
|
2409
|
+
return { ok: false, stage: 'execute' };
|
|
2410
|
+
}
|
|
2411
|
+
replayTarget = {
|
|
2412
|
+
name: targetName,
|
|
2413
|
+
view: targetView,
|
|
2414
|
+
texture: targetTexture,
|
|
2415
|
+
textureIdentity: getTextureIdentity(targetTexture),
|
|
2416
|
+
graphGeneration: graphAccess.graphGeneration,
|
|
2417
|
+
};
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
const executed = graph.execute(frame, runPass, graphInstrumentation);
|
|
2421
|
+
if (!executed.ok) {
|
|
2422
|
+
passTimingCapture?.abort({ code: executed.error.code });
|
|
2423
|
+
internals.errorRegistry.fire(executed.error);
|
|
2424
|
+
return { ok: false, stage: 'execute' };
|
|
2425
|
+
}
|
|
2426
|
+
const replayedPassNames = new Set<string>();
|
|
2427
|
+
let prefixCallbackCount = 0;
|
|
2428
|
+
let depthAnchorReceipt:
|
|
2429
|
+
| {
|
|
2430
|
+
readonly pass: { name: string; executionIndex: number };
|
|
2431
|
+
readonly view: TextureView;
|
|
2432
|
+
}
|
|
2433
|
+
| undefined;
|
|
2434
|
+
const replayRunPass: import('@forgeax/engine-render-graph').RenderGraphPassRunner = (
|
|
2435
|
+
pass,
|
|
2436
|
+
encode,
|
|
2437
|
+
) => {
|
|
2438
|
+
if (!requestedPassNames.has(pass.name)) return;
|
|
2439
|
+
if (replayedPassNames.has(pass.name)) {
|
|
2440
|
+
replayFailure(`replay-pass-selection-multiple-hit:${pass.name}`);
|
|
2441
|
+
return;
|
|
2442
|
+
}
|
|
2443
|
+
replayedPassNames.add(pass.name);
|
|
2444
|
+
const depthView = (pass as ResolvedDepthPassExecution).resolvedDepthStencilAttachmentView;
|
|
2445
|
+
if (onPrefixEncoded !== undefined) {
|
|
2446
|
+
if (pass.name === depthAttachmentPassName) {
|
|
2447
|
+
if (depthView === undefined) {
|
|
2448
|
+
replayFailure(`pass-replay-depth-attachment-missing:${pass.name}`);
|
|
2449
|
+
return;
|
|
2450
|
+
}
|
|
2451
|
+
const target = replayTarget;
|
|
2452
|
+
if (target === undefined || depthView !== target.view) {
|
|
2453
|
+
replayFailure(`pass-replay-attachment-target-mismatch:${pass.name}`);
|
|
2454
|
+
return;
|
|
2455
|
+
}
|
|
2456
|
+
if (depthAnchorReceipt !== undefined) {
|
|
2457
|
+
replayFailure(`pass-replay-depth-attachment-multiple-hit:${pass.name}`);
|
|
2458
|
+
return;
|
|
2459
|
+
}
|
|
2460
|
+
depthAnchorReceipt = {
|
|
2461
|
+
pass: { name: pass.name, executionIndex: pass.executionIndex },
|
|
2462
|
+
view: depthView,
|
|
2463
|
+
};
|
|
2464
|
+
}
|
|
2465
|
+
let encoded = false;
|
|
2466
|
+
const encodePrefix = () => {
|
|
2467
|
+
if (encoded) {
|
|
2468
|
+
replayFailure(`pass-replay-encode-multiple-hit:${pass.name}`);
|
|
2469
|
+
return;
|
|
2470
|
+
}
|
|
2471
|
+
encode();
|
|
2472
|
+
encoded = true;
|
|
2473
|
+
if (replayValidationFailed || pass.name !== observeAfterPassName) return;
|
|
2474
|
+
const target = replayTarget;
|
|
2475
|
+
const anchor = depthAnchorReceipt;
|
|
2476
|
+
if (target === undefined || anchor === undefined) {
|
|
2477
|
+
replayFailure('pass-replay-depth-attachment-anchor-missing-at-boundary');
|
|
2478
|
+
return;
|
|
2479
|
+
}
|
|
2480
|
+
const receipt: GraphTargetPassReplayPrefixReceipt = {
|
|
2481
|
+
passName: pass.name,
|
|
2482
|
+
executionIndex: pass.executionIndex,
|
|
2483
|
+
resolvedDepthStencilAttachmentView: anchor.view,
|
|
2484
|
+
graphGeneration: target.graphGeneration,
|
|
2485
|
+
targetName: target.name,
|
|
2486
|
+
targetView: target.view,
|
|
2487
|
+
targetTexture: target.texture,
|
|
2488
|
+
targetTextureIdentity: target.textureIdentity,
|
|
2489
|
+
replayPassNames: [...selectedReplayPassNames],
|
|
2490
|
+
depthAttachmentPassName: anchor.pass.name,
|
|
2491
|
+
observeAfterPassName: pass.name,
|
|
2492
|
+
depthAttachmentExecutionIndex: anchor.pass.executionIndex,
|
|
2493
|
+
};
|
|
2494
|
+
try {
|
|
2495
|
+
onPrefixEncoded(receipt);
|
|
2496
|
+
prefixCallbackCount += 1;
|
|
2497
|
+
} catch (cause) {
|
|
2498
|
+
replayFailure(
|
|
2499
|
+
`pass-replay-prefix-callback-threw:${pass.name}:${cause instanceof Error ? cause.message : String(cause)}`,
|
|
2500
|
+
);
|
|
2501
|
+
}
|
|
2502
|
+
};
|
|
2503
|
+
if (runPass === undefined) encodePrefix();
|
|
2504
|
+
else runPass(pass, encodePrefix);
|
|
2505
|
+
if (!encoded && !replayValidationFailed) {
|
|
2506
|
+
replayFailure(`pass-replay-encode-not-called:${pass.name}`);
|
|
2507
|
+
}
|
|
2508
|
+
return;
|
|
2509
|
+
}
|
|
2510
|
+
if (onPassEncoded === undefined) {
|
|
2511
|
+
if (runPass === undefined) encode();
|
|
2512
|
+
else runPass(pass, encode);
|
|
2513
|
+
return;
|
|
2514
|
+
}
|
|
2515
|
+
const target = replayTarget;
|
|
2516
|
+
if (target === undefined || depthView === undefined) {
|
|
2517
|
+
replayFailure(`pass-replay-depth-attachment-missing:${pass.name}`);
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2520
|
+
if (depthView !== target.view) {
|
|
2521
|
+
replayFailure(`pass-replay-attachment-target-mismatch:${pass.name}`);
|
|
2522
|
+
return;
|
|
2523
|
+
}
|
|
2524
|
+
let encoded = false;
|
|
2525
|
+
const encodeAndObserve = () => {
|
|
2526
|
+
if (encoded) {
|
|
2527
|
+
replayFailure(`pass-replay-encode-multiple-hit:${pass.name}`);
|
|
2528
|
+
return;
|
|
2529
|
+
}
|
|
2530
|
+
encode();
|
|
2531
|
+
encoded = true;
|
|
2532
|
+
if (replayValidationFailed) return;
|
|
2533
|
+
const receipt: GraphTargetPassReplayReceipt = {
|
|
2534
|
+
passName: pass.name,
|
|
2535
|
+
executionIndex: pass.executionIndex,
|
|
2536
|
+
resolvedDepthStencilAttachmentView: depthView,
|
|
2537
|
+
graphGeneration: target.graphGeneration,
|
|
2538
|
+
targetName: target.name,
|
|
2539
|
+
targetView: target.view,
|
|
2540
|
+
targetTexture: target.texture,
|
|
2541
|
+
targetTextureIdentity: target.textureIdentity,
|
|
2542
|
+
};
|
|
2543
|
+
try {
|
|
2544
|
+
onPassEncoded(receipt);
|
|
2545
|
+
} catch (cause) {
|
|
2546
|
+
replayFailure(
|
|
2547
|
+
`pass-replay-callback-threw:${pass.name}:${cause instanceof Error ? cause.message : String(cause)}`,
|
|
2548
|
+
);
|
|
2549
|
+
}
|
|
2550
|
+
};
|
|
2551
|
+
if (runPass === undefined) encodeAndObserve();
|
|
2552
|
+
else runPass(pass, encodeAndObserve);
|
|
2553
|
+
if (!encoded && !replayValidationFailed) {
|
|
2554
|
+
replayFailure(`pass-replay-encode-not-called:${pass.name}`);
|
|
2555
|
+
}
|
|
2556
|
+
};
|
|
2557
|
+
const replayed = graph.execute(frame, replayRunPass);
|
|
2558
|
+
if (!replayed.ok) {
|
|
2559
|
+
internals.errorRegistry.fire(replayed.error);
|
|
2560
|
+
return { ok: false, stage: 'execute' };
|
|
2561
|
+
}
|
|
2562
|
+
if (replayValidationFailed) return { ok: false, stage: 'execute' };
|
|
2563
|
+
if (replayedPassNames.size !== requestedPassNames.size) {
|
|
2564
|
+
replayFailure('replay-pass-selection-zero-hit');
|
|
2565
|
+
return { ok: false, stage: 'execute' };
|
|
2566
|
+
}
|
|
2567
|
+
if (onPrefixEncoded !== undefined && prefixCallbackCount !== 1) {
|
|
2568
|
+
replayFailure('pass-replay-prefix-callback-count-invalid');
|
|
2569
|
+
return { ok: false, stage: 'execute' };
|
|
2570
|
+
}
|
|
2571
|
+
} else {
|
|
2572
|
+
const executed = graph.execute(frame, runPass, graphInstrumentation);
|
|
2573
|
+
if (!executed.ok) {
|
|
2574
|
+
passTimingCapture?.abort({ code: executed.error.code });
|
|
2575
|
+
internals.errorRegistry.fire(executed.error);
|
|
2576
|
+
return { ok: false, stage: 'execute' };
|
|
2577
|
+
}
|
|
1673
2578
|
}
|
|
1674
|
-
|
|
2579
|
+
timingInstrumentationState?.setCapture(undefined);
|
|
2580
|
+
const afterGraphExecute = resolvedFrameHooks?.afterGraphExecute;
|
|
1675
2581
|
if (afterGraphExecute !== undefined) {
|
|
1676
2582
|
const recorded = afterGraphExecute();
|
|
1677
2583
|
if (!recorded.ok) {
|
|
@@ -1684,7 +2590,7 @@ export function executeCompiledFrameGraph(
|
|
|
1684
2590
|
finish: () => {
|
|
1685
2591
|
const graphCapture = frameState.graphTargetCapture;
|
|
1686
2592
|
frameState.graphTargetCapture = undefined;
|
|
1687
|
-
if (graphCapture !== undefined) {
|
|
2593
|
+
if (graphCapture !== undefined && graphCapture.kind !== 'pass-replay') {
|
|
1688
2594
|
const graphAccess = frameState.perFrameGraph;
|
|
1689
2595
|
const graphTexture = graphAccess?.getColorTargetTexture(graphCapture.name);
|
|
1690
2596
|
const descriptor = graphAccess?.getColorTargetDescriptor(graphCapture.name);
|
|
@@ -1903,7 +2809,8 @@ export function executeCompiledFrameGraph(
|
|
|
1903
2809
|
},
|
|
1904
2810
|
}),
|
|
1905
2811
|
commit: () => {
|
|
1906
|
-
|
|
2812
|
+
resolvedFrameHooks?.onSubmitted?.();
|
|
2813
|
+
legacySubmitCommit?.();
|
|
1907
2814
|
if (frameState.temporalFrameInput !== undefined) {
|
|
1908
2815
|
const temporal = frameState.temporalFrameTransaction.commit({ accepted: true });
|
|
1909
2816
|
if (temporal.ok) {
|
|
@@ -1931,6 +2838,46 @@ export function executeCompiledFrameGraph(
|
|
|
1931
2838
|
?.perPassResources.commitBloomFrameReceipts?.(frameState.bloomFrameReceipts);
|
|
1932
2839
|
frameState.bloomFrameReceipts = undefined;
|
|
1933
2840
|
}
|
|
2841
|
+
const pendingAuto = frameState.pendingAutoExposureGpuResources;
|
|
2842
|
+
if (pendingAuto !== undefined) {
|
|
2843
|
+
const previousAuto = frameState.autoExposureGpuResources;
|
|
2844
|
+
frameState.autoExposureGpuResources = pendingAuto;
|
|
2845
|
+
frameState.pendingAutoExposureGpuResources = undefined;
|
|
2846
|
+
if (previousAuto !== undefined && previousAuto !== pendingAuto) {
|
|
2847
|
+
internals.device.queue
|
|
2848
|
+
.onSubmittedWorkDone()
|
|
2849
|
+
.then(() => retireAutoExposureGpuResources(previousAuto))
|
|
2850
|
+
.catch(() => undefined);
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
const pendingAutoState = frameState.pendingAutoExposureState;
|
|
2854
|
+
if (pendingAutoState !== undefined) {
|
|
2855
|
+
frameState.autoExposureState = commitAutoExposureSubmission(
|
|
2856
|
+
pendingAutoState.state,
|
|
2857
|
+
pendingAutoState,
|
|
2858
|
+
);
|
|
2859
|
+
frameState.pendingAutoExposureState = undefined;
|
|
2860
|
+
}
|
|
2861
|
+
const pendingLut = frameState.pendingStandardLutGpuResources;
|
|
2862
|
+
if (pendingLut !== undefined) {
|
|
2863
|
+
const previousLut = frameState.standardLutGpuResources;
|
|
2864
|
+
frameState.standardLutGpuResources = pendingLut;
|
|
2865
|
+
frameState.pendingStandardLutGpuResources = undefined;
|
|
2866
|
+
if (previousLut !== undefined && previousLut !== pendingLut) {
|
|
2867
|
+
retireStandardLutGpuResources(previousLut);
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
const pendingLutState = frameState.pendingStandardLutState;
|
|
2871
|
+
if (pendingLutState !== undefined) {
|
|
2872
|
+
frameState.standardLutState =
|
|
2873
|
+
pendingLutState.remove || pendingLutState.candidate === undefined
|
|
2874
|
+
? resetStandardLutState(pendingLutState.state, 'resource-removed', {
|
|
2875
|
+
targetGeneration: pendingLutState.targetGeneration,
|
|
2876
|
+
deviceEpoch: pendingLutState.deviceEpoch,
|
|
2877
|
+
})
|
|
2878
|
+
: commitStandardLutCandidate(pendingLutState.state, pendingLutState.candidate);
|
|
2879
|
+
frameState.pendingStandardLutState = undefined;
|
|
2880
|
+
}
|
|
1934
2881
|
const stagedGpuState = frameState.temporalGpuState;
|
|
1935
2882
|
if (stagedGpuState !== undefined) {
|
|
1936
2883
|
if (commitTemporalGpuSubmit(stagedGpuState)) {
|
|
@@ -1993,15 +2940,28 @@ export function executeCompiledFrameGraph(
|
|
|
1993
2940
|
frameState.environmentLifecycle?.publish(frameState.environmentGeneration);
|
|
1994
2941
|
frameState.environmentGeneration = undefined;
|
|
1995
2942
|
}
|
|
2943
|
+
frameState.pendingAtmospherePublish?.();
|
|
2944
|
+
frameState.pendingAtmospherePublish = undefined;
|
|
1996
2945
|
onSubmitted?.(internals.device.queue.onSubmittedWorkDone());
|
|
1997
2946
|
},
|
|
1998
2947
|
abort: (failure) => {
|
|
1999
|
-
|
|
2948
|
+
frameState.pendingAtmospherePublish = undefined;
|
|
2949
|
+
resolvedFrameHooks?.onAborted?.();
|
|
2000
2950
|
passTimingCapture?.abort({ code: failure.stage });
|
|
2001
2951
|
timingHost.gpuPassTimingCapture = undefined;
|
|
2002
2952
|
timingHost.gpuPassTimingSubmittedWork = undefined;
|
|
2003
2953
|
timingCapture?.discard();
|
|
2004
2954
|
frameState.bloomFrameReceipts = undefined;
|
|
2955
|
+
frameState.pendingAutoExposureState = undefined;
|
|
2956
|
+
frameState.pendingStandardLutState = undefined;
|
|
2957
|
+
if (frameState.pendingAutoExposureGpuResources !== undefined) {
|
|
2958
|
+
retireAutoExposureGpuResources(frameState.pendingAutoExposureGpuResources);
|
|
2959
|
+
frameState.pendingAutoExposureGpuResources = undefined;
|
|
2960
|
+
}
|
|
2961
|
+
if (frameState.pendingStandardLutGpuResources !== undefined) {
|
|
2962
|
+
retireStandardLutGpuResources(frameState.pendingStandardLutGpuResources);
|
|
2963
|
+
frameState.pendingStandardLutGpuResources = undefined;
|
|
2964
|
+
}
|
|
2005
2965
|
if (frameState.environmentGeneration !== undefined) {
|
|
2006
2966
|
frameState.environmentLifecycle?.recordStageFailure(
|
|
2007
2967
|
failure.stage,
|