@forgeax/engine-render 0.1.28 → 0.1.30
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 +856 -126
- package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
- package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/device-feature-admission.d.ts +4 -3
- package/dist/assembly/device-feature-admission.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-host.d.ts +27 -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 +14 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +31 -1
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +24 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -0
- 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/device-loss-fanout.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/recovery-attempt.d.ts +1 -6
- package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +7 -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 +7 -1
- 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/capture/scene-projection.d.ts +41 -0
- package/dist/capture/scene-projection.d.ts.map +1 -0
- package/dist/{chunk-J52NMQKR.mjs → chunk-7MQ3XBSP.mjs} +1098 -844
- package/dist/chunk-7MQ3XBSP.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-VSL23LZE.mjs → chunk-C3DDSXYK.mjs} +1188 -463
- package/dist/chunk-C3DDSXYK.mjs.map +1 -0
- package/dist/{chunk-IQMKJLNU.mjs → chunk-FUUO4UND.mjs} +443 -30
- package/dist/chunk-FUUO4UND.mjs.map +1 -0
- package/dist/{chunk-J6KACNOH.mjs → chunk-JRBDO2KB.mjs} +617 -7
- package/dist/chunk-JRBDO2KB.mjs.map +1 -0
- package/dist/{chunk-GE3SDD72.mjs → chunk-MDQJPY3T.mjs} +20 -40
- package/dist/chunk-MDQJPY3T.mjs.map +1 -0
- package/dist/{chunk-MYJ5RPJO.mjs → chunk-NO4WZCAH.mjs} +3 -3
- package/dist/chunk-NO4WZCAH.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-MBU4ZVE7.mjs → chunk-PSEQ6QPH.mjs} +4655 -892
- package/dist/chunk-PSEQ6QPH.mjs.map +1 -0
- package/dist/{chunk-JAASCMXA.mjs → chunk-S5UE2T5P.mjs} +289 -41
- package/dist/chunk-S5UE2T5P.mjs.map +1 -0
- package/dist/components/camera.d.ts +62 -2
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/directional-light.d.ts +2 -2
- package/dist/components/dynamic-resolution.d.ts +15 -0
- package/dist/components/dynamic-resolution.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +6 -20
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/reflection-probe.d.ts +1 -0
- package/dist/components/reflection-probe.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/components/skylight.d.ts +4 -1
- package/dist/components/skylight.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +14809 -7570
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/device-scope.d.ts +2 -0
- package/dist/device/device-scope.d.ts.map +1 -1
- package/dist/device/gpu-residency.d.ts +3 -14
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/environment/background.d.ts +7 -0
- package/dist/environment/background.d.ts.map +1 -0
- package/dist/environment/ibl.d.ts +11 -0
- package/dist/environment/ibl.d.ts.map +1 -0
- package/dist/environment/storage.d.ts +14 -0
- package/dist/environment/storage.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 +41 -4
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +7 -0
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +50 -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/material-artifacts.d.ts +24 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -0
- package/dist/gpu-driven/material-bindings.d.ts +7 -0
- package/dist/gpu-driven/material-bindings.d.ts.map +1 -0
- 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 +2 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +169 -27
- 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-resource.d.ts +5 -2
- package/dist/gpu-resource.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 +9 -0
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +2 -0
- package/dist/ibl/IblPipelineCache.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 +3 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +87 -75
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +10 -8
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +180 -1
- 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 +15 -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 +23 -5
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/render-extent.d.ts +51 -0
- package/dist/pipeline/render-extent.d.ts.map +1 -0
- package/dist/pipeline/standard-build-context.d.ts +7 -0
- package/dist/pipeline/standard-build-context.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts +3 -2
- 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/standard-profile.d.ts +2 -1
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +5 -2
- 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/plugin.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/post-process-errors.d.ts +9 -2
- package/dist/post-process-errors.d.ts.map +1 -1
- package/dist/prepare/extended-lighting/resources.d.ts +3 -3
- 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 +109 -13
- 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 +41 -5
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +13 -9
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +43 -3
- 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 +14 -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 +1 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +101 -22
- 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 +39 -8
- 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/background.d.ts +14 -0
- package/dist/reflection/background.d.ts.map +1 -0
- package/dist/reflection/filter.d.ts.map +1 -1
- package/dist/reflection/projection.d.ts +1 -0
- package/dist/reflection/projection.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts +4 -4
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +211 -53
- 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 +81 -6
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +15 -6
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +128 -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 +31 -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/ssao-config.d.ts +8 -6
- package/dist/ssao-config.d.ts.map +1 -1
- 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 +4 -2
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts +15 -0
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -0
- package/dist/temporal/temporal-view.d.ts +6 -0
- package/dist/temporal/temporal-view.d.ts.map +1 -1
- package/dist/temporal/view.d.ts +6 -0
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +41 -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/component.d.ts +1 -0
- package/dist/volume/component.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__/capture-scene-projection.unit.test.ts +24 -0
- package/src/__tests__/detached-inspection.integration.test.ts +5 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +15 -24
- package/src/__tests__/device-loss-fanout.unit.test.ts +43 -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__/dynamic-geometry-batch.unit.test.ts +157 -0
- package/src/__tests__/dynamic-geometry.unit.test.ts +36 -0
- package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +81 -0
- package/src/__tests__/factory-contract.integration.test.ts +231 -9
- 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-observation.contract.test.ts +21 -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 +307 -7
- 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 +261 -0
- package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +346 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1422 -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 +1076 -106
- 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 +160 -52
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +15 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +20 -2
- package/src/__tests__/gpu-resource-scope.unit.test.ts +71 -0
- 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 +613 -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 +57 -3
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +8 -0
- package/src/__tests__/morph-neutral-admission.unit.test.ts +19 -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 +42 -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__/post-process-error-policy-owner.unit.test.ts +6 -5
- 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 +251 -9
- 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 +171 -0
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +12 -10
- package/src/__tests__/reflection-probe-box.dawn.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +9 -0
- package/src/__tests__/reflection-probe-orientation.dawn.test.ts +294 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +5 -14
- package/src/__tests__/reflection-probe-updates.unit.test.ts +129 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +7 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +27 -1
- package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
- package/src/__tests__/render-extent.unit.test.ts +63 -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 +915 -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 +233 -9
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
- package/src/__tests__/shader-manifest-fixture.ts +45 -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 +125 -14
- package/src/__tests__/specular-environment-scale.dawn.test.ts +158 -0
- package/src/__tests__/ssao-config.unit.test.ts +7 -0
- package/src/__tests__/ssao-surface.dawn.test.ts +252 -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-cube-silhouette.dawn.test.ts +270 -0
- package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +99 -0
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +116 -0
- package/src/__tests__/ssr-gpu-dispatch.ts +951 -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 +84 -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 +275 -0
- package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
- package/src/__tests__/standard-profile-oracle.unit.test.ts +49 -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 +199 -0
- package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
- package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +782 -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 +342 -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__/temporal-view.unit.test.ts +17 -0
- package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
- package/src/__tests__/transmission-prewarm.unit.test.ts +57 -0
- 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/__tests__/volumetric-fog-stage-readback.dawn.test.ts +62 -13
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +7 -7
- package/src/assembly/atmosphere-shader-prewarm.ts +39 -0
- package/src/assembly/device-feature-admission.ts +9 -4
- package/src/assembly/dynamic-geometry-host.ts +284 -163
- 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 +19 -0
- package/src/assembly/material/assembly.ts +383 -1
- package/src/assembly/material/pipeline-helpers.ts +100 -0
- package/src/assembly/material-shader-policy.ts +110 -46
- package/src/assembly/recovery/device-loss-fanout.ts +5 -0
- package/src/assembly/recovery/failure-location.ts +62 -0
- package/src/assembly/recovery/recovery-attempt.ts +2 -29
- package/src/assembly/recovery/renderer-recover.ts +16 -17
- package/src/assembly/renderer-facade.ts +34 -1
- 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 +46 -1
- 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 +161 -131
- 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 +744 -730
- package/src/assembly/webgpu-vertex-layouts.ts +233 -87
- package/src/capture/scene-projection.ts +37 -0
- package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
- package/src/components/__tests__/dynamic-resolution-schema.unit.test.ts +65 -0
- package/src/components/__tests__/light-radius.integration.test.ts +59 -0
- package/src/components/camera.ts +287 -7
- package/src/components/directional-light.ts +3 -3
- package/src/components/dynamic-resolution.ts +67 -0
- package/src/components/index.ts +2 -0
- package/src/components/instances.ts +45 -18
- package/src/components/light-helpers.ts +6 -1
- package/src/components/reflection-probe.ts +1 -0
- package/src/components/scene-instance.ts +2 -1
- package/src/components/screen-space-reflection.ts +21 -0
- package/src/components/skylight.ts +4 -1
- package/src/components/sprite-animation.ts +2 -2
- package/src/components/sprite-instances.ts +1 -1
- package/src/device/device-scope.ts +13 -7
- package/src/device/gpu-residency.ts +45 -42
- package/src/dynamic-geometry.ts +13 -8
- package/src/environment/background.ts +281 -0
- package/src/environment/ibl.ts +211 -0
- package/src/environment/storage.ts +63 -0
- package/src/errors/gpu-driven.ts +49 -8
- package/src/errors/render.ts +91 -3
- package/src/extract/camera.ts +37 -1
- package/src/extract/contracts.ts +10 -0
- package/src/extract/gpu-driven.ts +240 -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 +452 -108
- package/src/gpu-driven/material-artifacts.ts +179 -0
- package/src/gpu-driven/material-bindings.ts +41 -0
- package/src/gpu-driven/pbr-program.ts +31 -0
- package/src/gpu-driven/prepared-draw.ts +42 -6
- package/src/gpu-driven/production-raster.ts +2806 -716
- package/src/gpu-driven/shadow-views.ts +539 -0
- package/src/gpu-driven/view-gpu.ts +188 -41
- package/src/gpu-resource.ts +21 -2
- package/src/gpu-scene-schema.ts +61 -11
- package/src/gpu-scene.ts +197 -99
- package/src/gpu-texture-usage.ts +1 -0
- package/src/hdrp-buffers.ts +141 -36
- package/src/ibl/IblPipelineCache.ts +5 -0
- package/src/ibl/frame-resources.ts +38 -0
- package/src/ibl/skylight-bind-group.ts +32 -21
- package/src/index.ts +194 -75
- package/src/inspection-types.ts +207 -1
- 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 +194 -0
- package/src/materials.ts +44 -8
- package/src/pbr-pipeline.ts +172 -19
- package/src/pipeline/render-extent.ts +111 -0
- package/src/pipeline/standard-build-context.ts +7 -0
- package/src/pipeline/standard-forward-lane.ts +74 -29
- 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 +232 -70
- package/src/pipeline/standard-post.ts +190 -27
- package/src/pipeline/standard-profile.ts +2 -1
- package/src/pipeline-builder.ts +28 -9
- package/src/pipeline-spec-types.ts +4 -0
- package/src/pipeline-spec.ts +37 -29
- package/src/plugin.ts +4 -0
- package/src/points-lines/standard-owner.ts +6 -14
- package/src/post-process-errors.ts +26 -18
- package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +2 -2
- package/src/prepare/extended-lighting/resources.ts +3 -3
- package/src/prepare/prepared-graphics-resolver.ts +9 -2
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +68 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +45 -0
- package/src/record/__tests__/material-slot-plan.unit.test.ts +57 -0
- package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +20 -1
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +41 -6
- package/src/record/__tests__/temporal-payload.unit.test.ts +2 -0
- 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 +15 -12
- package/src/record/frame-snapshot.ts +146 -34
- package/src/record/frame-targets.ts +9 -0
- package/src/record/frame.ts +838 -170
- package/src/record/main-pass-geometry.ts +209 -103
- package/src/record/main-pass-material.ts +157 -40
- package/src/record/main-pass-sprite-draws.ts +16 -107
- package/src/record/main-pass.ts +141 -12
- package/src/record/material-uniforms.ts +1 -1
- package/src/record/mesh-ssbo.ts +59 -15
- package/src/record/prepared-material-bindings.ts +238 -0
- package/src/record/recovery-pipeline.ts +69 -90
- package/src/record/render-context.ts +123 -24
- package/src/record/shadow-pass.ts +1389 -230
- package/src/record/skybox-post-pass.ts +14 -3
- package/src/record/typed-frame-graph.ts +1064 -47
- package/src/record/view-ubo.ts +12 -1
- package/src/recovery/render-system-candidate.ts +135 -68
- package/src/recovery/render-system-roots.ts +113 -0
- package/src/recovery/types.ts +77 -0
- package/src/reflection/background.ts +151 -0
- package/src/reflection/filter.ts +3 -0
- package/src/reflection/projection.ts +16 -6
- package/src/reflection/record-owner.ts +308 -140
- package/src/render-contract.ts +237 -49
- package/src/render-graph-primitives.ts +34 -5
- package/src/render-pipeline.ts +90 -2
- package/src/render-system-extract-tail.ts +431 -162
- package/src/render-system-extract.ts +478 -119
- package/src/render-system-projections.ts +241 -0
- package/src/render-system.ts +715 -828
- package/src/scene/render-scene-types.ts +13 -4
- package/src/scene/render-scene.ts +577 -355
- package/src/scene/shadow-visibility.ts +21 -0
- package/src/ssao-config.ts +25 -8
- 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 +797 -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 +79 -12
- package/src/temporal/history.ts +3 -1
- package/src/temporal/inspection.ts +2 -1
- package/src/temporal/standard-scene-data.ts +10 -2
- package/src/temporal/target-coverage-attachment.ts +72 -0
- package/src/temporal/temporal-view.ts +11 -2
- package/src/temporal/view.ts +12 -2
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +219 -139
- package/src/typed-render-graph-primitives.ts +304 -74
- package/src/typed-shadow-passes.ts +122 -12
- package/src/volume/component.ts +1 -0
- package/src/volume/passes.ts +3 -3
- 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-MYJ5RPJO.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
package/src/render-system.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { projectCaptureScene } from './capture/scene-projection';
|
|
2
|
+
import type { RenderSceneBounds } from './scene/render-scene-types';
|
|
1
3
|
// @forgeax/engine-runtime - RenderSystem main entry (D-S2 three-stage Extract ->
|
|
2
4
|
// Prepare -> Record + 4-tier error fan-out).
|
|
3
5
|
//
|
|
@@ -16,31 +18,17 @@
|
|
|
16
18
|
// .invert` (charter proposition 5: no math reinvention; render-system.test.ts
|
|
17
19
|
// asserts `/@forgeax\/engine-math/` shows up in render-system.ts source).
|
|
18
20
|
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
numMipLevels,
|
|
22
|
-
resolveAssetHandle,
|
|
23
|
-
} from '@forgeax/engine-assets-runtime';
|
|
24
|
-
import type { World } from '@forgeax/engine-ecs';
|
|
21
|
+
import { numMipLevels, resolveAssetHandle } from '@forgeax/engine-assets-runtime';
|
|
22
|
+
import { Time, type World } from '@forgeax/engine-ecs';
|
|
25
23
|
import type { RenderReadLease } from '@forgeax/engine-ecs/projection';
|
|
26
24
|
import type { RecorderSession } from '@forgeax/engine-profiler';
|
|
27
25
|
import type { CompiledRenderGraphInfo } from '@forgeax/engine-render-graph';
|
|
28
|
-
import type {
|
|
29
|
-
BindGroupEntry,
|
|
30
|
-
BindGroupLayout,
|
|
31
|
-
Buffer,
|
|
32
|
-
RenderPipeline,
|
|
33
|
-
RhiDevice,
|
|
34
|
-
} from '@forgeax/engine-rhi';
|
|
26
|
+
import type { BindGroupLayout, Buffer, RenderPipeline, RhiDevice } from '@forgeax/engine-rhi';
|
|
35
27
|
import { err, ok, type Result, RhiError } from '@forgeax/engine-rhi';
|
|
36
28
|
import {
|
|
37
|
-
derive,
|
|
38
29
|
deriveTextureLayout,
|
|
39
|
-
type Handle,
|
|
40
30
|
type MaterialAsset,
|
|
41
|
-
type MaterialTextureValue,
|
|
42
31
|
type RenderPipelineAsset,
|
|
43
|
-
RenderQueue,
|
|
44
32
|
type SamplerAsset,
|
|
45
33
|
type TextureAsset,
|
|
46
34
|
toShared,
|
|
@@ -50,9 +38,8 @@ import {
|
|
|
50
38
|
directionalShadowProfileFromQuality,
|
|
51
39
|
projectDirectionalShadowInspectionSource,
|
|
52
40
|
} from './assembly/directional-shadow-inspection';
|
|
41
|
+
import { createGpuDrivenOwner } from './assembly/gpu-driven-owner';
|
|
53
42
|
import { createClusterBinScratch } from './cluster-binner';
|
|
54
|
-
import type { DeviceScope, LifecycleResourceSpec } from './device/device-scope';
|
|
55
|
-
import type { EnvironmentGeneration } from './environment/generation';
|
|
56
43
|
import { EnvironmentLifecycle } from './environment/lifecycle';
|
|
57
44
|
import {
|
|
58
45
|
type ObservationUnavailableError,
|
|
@@ -60,11 +47,11 @@ import {
|
|
|
60
47
|
TransmissionCapabilityMissingError,
|
|
61
48
|
} from './errors/render';
|
|
62
49
|
import {
|
|
63
|
-
type RenderFeatureHost,
|
|
64
50
|
type RenderFeaturePreparedGraphicsResolverInput,
|
|
65
51
|
runRenderFeatureFrame,
|
|
66
52
|
settlePreparedGraphicsCompletion,
|
|
67
53
|
} from './features/host';
|
|
54
|
+
import { createFeatureNoiseResolver } from './features/noise-texture';
|
|
68
55
|
import {
|
|
69
56
|
createRenderFeatureGpuWorkOwner,
|
|
70
57
|
type RenderFeatureGpuWorkOwner,
|
|
@@ -79,22 +66,45 @@ import {
|
|
|
79
66
|
postProcessShaderModuleLabel,
|
|
80
67
|
postProcessShaderPipelineLabel,
|
|
81
68
|
} from './fullscreen-post-process-pass';
|
|
82
|
-
import { GpuDrivenProduction } from './gpu-driven/production-raster';
|
|
83
69
|
import type {
|
|
84
70
|
BloomInspection,
|
|
85
71
|
DirectionalShadowInspection,
|
|
86
72
|
GpuDrivenProductionInspection,
|
|
87
73
|
LodOcclusionInspection,
|
|
88
|
-
|
|
89
|
-
LodOcclusionWorldInspection,
|
|
74
|
+
MaterialTextureSourceInspection,
|
|
90
75
|
MotionBlurInspection,
|
|
91
76
|
ReflectionProbeInspection,
|
|
92
77
|
RenderSceneInspection,
|
|
93
78
|
SsrDependenciesInspection,
|
|
79
|
+
SsrSpatialInspection,
|
|
94
80
|
TemporalTargetInspection,
|
|
95
81
|
TransmissionInspection,
|
|
96
82
|
} from './inspection-types';
|
|
97
83
|
import { buildOcclusionProxyVertices } from './occlusion-proxy';
|
|
84
|
+
import {
|
|
85
|
+
AUTO_EXPOSURE_HISTOGRAM_BYTES,
|
|
86
|
+
retireAutoExposureGpuResources,
|
|
87
|
+
writeAutoExposureParameters,
|
|
88
|
+
} from './pipeline/standard-output/auto-exposure/gpu';
|
|
89
|
+
import {
|
|
90
|
+
type AutoExposureInspection,
|
|
91
|
+
createAutoExposureInspection,
|
|
92
|
+
} from './pipeline/standard-output/auto-exposure/inspection';
|
|
93
|
+
import {
|
|
94
|
+
createAutoExposureState,
|
|
95
|
+
resetAutoExposureState,
|
|
96
|
+
} from './pipeline/standard-output/auto-exposure/state';
|
|
97
|
+
import {
|
|
98
|
+
createStandardLutState,
|
|
99
|
+
inspectStandardLutState,
|
|
100
|
+
prepareStandardLutCandidate,
|
|
101
|
+
resetStandardLutState,
|
|
102
|
+
type StandardLutInspection,
|
|
103
|
+
} from './pipeline/standard-output/lut-state';
|
|
104
|
+
import {
|
|
105
|
+
prepareStandardOutputResources,
|
|
106
|
+
resetStandardOutputForDeviceLoss,
|
|
107
|
+
} from './pipeline/standard-output/resources';
|
|
98
108
|
import type { PointsLinesRetainedSnapshot } from './points-lines/snapshot';
|
|
99
109
|
import { StandardPointsLinesOwner } from './points-lines/standard-owner';
|
|
100
110
|
import {
|
|
@@ -102,6 +112,35 @@ import {
|
|
|
102
112
|
materialSamplerHandles,
|
|
103
113
|
materialTextureHandles,
|
|
104
114
|
} from './recovery/render-system-candidate';
|
|
115
|
+
|
|
116
|
+
export { materialTextureHandlesForResidency } from './recovery/render-system-candidate';
|
|
117
|
+
|
|
118
|
+
import {
|
|
119
|
+
createDynamicGeometryFrameBindings,
|
|
120
|
+
resetDynamicGeometryTemporalHistory,
|
|
121
|
+
} from './record/dynamic-geometry-consumption';
|
|
122
|
+
import type {
|
|
123
|
+
RecoveryGraphCandidate,
|
|
124
|
+
RecoveryGraphCandidatePreparation,
|
|
125
|
+
RecoveryGraphCandidateRuntime,
|
|
126
|
+
RecoveryGraphSetupSubmission,
|
|
127
|
+
RecoveryPostProcessResources,
|
|
128
|
+
RecoveryRootBundle,
|
|
129
|
+
RecoveryRootRuntime,
|
|
130
|
+
} from './recovery/types';
|
|
131
|
+
|
|
132
|
+
export type {
|
|
133
|
+
RecoveryGraphCandidate,
|
|
134
|
+
RecoveryGraphCandidatePreparation,
|
|
135
|
+
RecoveryGraphCandidateRuntime,
|
|
136
|
+
RecoveryGraphSetupSubmission,
|
|
137
|
+
RecoveryPointsLinesCandidate,
|
|
138
|
+
RecoveryPostProcessResources,
|
|
139
|
+
RecoveryRootBundle,
|
|
140
|
+
RecoveryRootRuntime,
|
|
141
|
+
} from './recovery/types';
|
|
142
|
+
|
|
143
|
+
import { prepareRenderSystemRecoveryRoots } from './recovery/render-system-roots';
|
|
105
144
|
import { ReflectionProbeRecordOwner } from './reflection/record-owner';
|
|
106
145
|
import {
|
|
107
146
|
OcclusionRenderRuntime,
|
|
@@ -113,18 +152,18 @@ import { inspectVolumetricFog } from './volume/inspection';
|
|
|
113
152
|
export type { RenderSceneInspection } from './inspection-types';
|
|
114
153
|
|
|
115
154
|
import { createCubeCaptureScheduler } from './capture/scheduler';
|
|
116
|
-
import type { GpuResidencyCache } from './device/gpu-residency';
|
|
117
155
|
import type { EnvironmentInspection } from './environment/inspection';
|
|
156
|
+
import { gpuDrivenShadowDrawKey } from './extract/gpu-driven';
|
|
118
157
|
import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from './gpu-usage';
|
|
119
158
|
import { resetHdrpBuffers } from './hdrp-buffers';
|
|
120
|
-
import {
|
|
159
|
+
import type { SkylightBindGroupResources } from './ibl/skylight-bind-group';
|
|
121
160
|
import {
|
|
122
161
|
disposeInstanceBufferChunks,
|
|
123
162
|
disposeInstanceBuffers,
|
|
124
163
|
disposeTransientInstanceBuffers,
|
|
125
164
|
} from './instance-buffer-cache';
|
|
126
165
|
import type { InstanceCollectionInspection } from './instances';
|
|
127
|
-
import {
|
|
166
|
+
import { InstanceCollectionStore } from './instances';
|
|
128
167
|
import {
|
|
129
168
|
type MeshMaterialBindingObservation,
|
|
130
169
|
type MeshMaterialBindingPreparationFailure,
|
|
@@ -163,12 +202,18 @@ import type {
|
|
|
163
202
|
GpuPassTimingSession,
|
|
164
203
|
} from './record/gpu-pass-timing/session';
|
|
165
204
|
import type { GpuTimingCapture } from './record/gpu-timing';
|
|
166
|
-
import {
|
|
167
|
-
import
|
|
205
|
+
import { resolveMaterialSkylight } from './record/main-pass-material';
|
|
206
|
+
import {
|
|
207
|
+
createPreparedResolverCaches,
|
|
208
|
+
type PreparedResolverCaches,
|
|
209
|
+
preparedMaterialBindings,
|
|
210
|
+
} from './record/prepared-material-bindings';
|
|
168
211
|
import type { PipelineState, RenderSystemInternals } from './record/render-context';
|
|
169
212
|
import type { CubeCaptureGraphState } from './record/typed-frame-graph';
|
|
170
213
|
import {
|
|
214
|
+
getRenderFeatureGraphInspection,
|
|
171
215
|
type RenderFeatureGraphCandidate,
|
|
216
|
+
recordRenderFeatureCandidate,
|
|
172
217
|
resetRenderFeatureGraphState,
|
|
173
218
|
settleVolumetricFogGraphCandidate,
|
|
174
219
|
} from './record/typed-frame-graph';
|
|
@@ -182,27 +227,27 @@ import {
|
|
|
182
227
|
} from './render-contract';
|
|
183
228
|
import type {
|
|
184
229
|
DispatchEntry,
|
|
185
|
-
ExtractedFrame,
|
|
186
230
|
ExtractedLights,
|
|
187
231
|
MaterialSnapshot,
|
|
188
232
|
RenderableSnapshot,
|
|
233
|
+
ShadowCasterMembership,
|
|
189
234
|
} from './render-system-extract';
|
|
190
235
|
import { extractFrames } from './render-system-extract';
|
|
191
236
|
import {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
} from './scene/render-scene';
|
|
237
|
+
canonicalizeWorldComposition,
|
|
238
|
+
createLodWorldInspections,
|
|
239
|
+
} from './render-system-projections';
|
|
240
|
+
import { PersistentRenderScene } from './scene/render-scene';
|
|
196
241
|
import { inspectLodOcclusion } from './scene/visibility/inspection';
|
|
197
242
|
import { resolveSsaoParameters } from './ssao-config';
|
|
198
|
-
import { projectSsrDependencies, resolveSsrAdmissionGeneration } from './ssr/admission';
|
|
199
243
|
import {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
} from './
|
|
244
|
+
projectSsrDependencies,
|
|
245
|
+
resolveSsrAdmissionGeneration,
|
|
246
|
+
type SsrSpatialAdmission,
|
|
247
|
+
zeroSsrAdmissionWork,
|
|
248
|
+
} from './ssr/admission';
|
|
249
|
+
import { projectSsrSpatialInspection } from './ssr/inspection';
|
|
250
|
+
import { sortTransparentDispatch } from './systems/transparent-dispatch';
|
|
206
251
|
import type { RenderTarget } from './targets/contracts';
|
|
207
252
|
import { createTemporalFrameTransaction, type TemporalFrame } from './temporal/frame';
|
|
208
253
|
import { retireTemporalGpuState } from './temporal/gpu';
|
|
@@ -219,147 +264,71 @@ import {
|
|
|
219
264
|
inspectTransmissionFromAdmission,
|
|
220
265
|
} from './transmission/inspection';
|
|
221
266
|
|
|
222
|
-
|
|
267
|
+
const WORLD_ENTITY_KEY_STRIDE = 4294967296;
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Extract emits world/entity keys in the transient `worlds[]` index domain,
|
|
271
|
+
* while PersistentRenderScene owns stable renderer-local World keys for the
|
|
272
|
+
* retained GPU scene. Rebase ShadowCaster ownership at this orchestration
|
|
273
|
+
* boundary before both GPU projection and CPU residual recording consume it.
|
|
274
|
+
*/
|
|
275
|
+
function rebaseShadowCasterOwnership(
|
|
223
276
|
worlds: readonly World[],
|
|
224
|
-
|
|
225
|
-
|
|
277
|
+
stableWorldKeys: readonly number[],
|
|
278
|
+
entityKeys: ReadonlySet<number>,
|
|
279
|
+
drawKeys: ReadonlySet<string>,
|
|
280
|
+
membership: readonly ShadowCasterMembership[] | undefined,
|
|
226
281
|
): {
|
|
227
|
-
readonly
|
|
228
|
-
readonly
|
|
229
|
-
readonly
|
|
282
|
+
readonly entityKeys: ReadonlySet<number>;
|
|
283
|
+
readonly drawKeys: ReadonlySet<string>;
|
|
284
|
+
readonly membership: readonly ShadowCasterMembership[] | undefined;
|
|
230
285
|
} {
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
leases === undefined
|
|
243
|
-
? undefined
|
|
244
|
-
: Object.freeze(
|
|
245
|
-
order.map((entry) => leases[entry.index]).filter((lease) => lease !== undefined),
|
|
246
|
-
),
|
|
286
|
+
const rebaseWorldEntity = (composite: number): number => {
|
|
287
|
+
const transientWorldId = Math.floor(composite / WORLD_ENTITY_KEY_STRIDE);
|
|
288
|
+
if (
|
|
289
|
+
!Number.isInteger(transientWorldId) ||
|
|
290
|
+
transientWorldId < 0 ||
|
|
291
|
+
transientWorldId >= worlds.length
|
|
292
|
+
) {
|
|
293
|
+
return composite;
|
|
294
|
+
}
|
|
295
|
+
const entityKey = composite - transientWorldId * WORLD_ENTITY_KEY_STRIDE;
|
|
296
|
+
return worldEntityKey(stableWorldKeys[transientWorldId] ?? transientWorldId, entityKey);
|
|
247
297
|
};
|
|
248
|
-
}
|
|
249
298
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
lodVisible: 0,
|
|
284
|
-
lodSamples: [] as RenderableSnapshot[],
|
|
285
|
-
}));
|
|
286
|
-
// Keep this projection bounded: the old implementation filtered the full
|
|
287
|
-
// 100k renderable list twice per World on every frame and retained another
|
|
288
|
-
// Set-backed traversal just to derive the six counters below. One pass is
|
|
289
|
-
// enough because the inspection only needs counts, the first row identity,
|
|
290
|
-
// and at most 64 detached samples.
|
|
291
|
-
for (const renderable of renderables) {
|
|
292
|
-
const accumulator = accumulators[renderable.worldId];
|
|
293
|
-
if (accumulator === undefined) continue;
|
|
294
|
-
const visible = submitted.has(renderable);
|
|
295
|
-
accumulator.allCount += 1;
|
|
296
|
-
if (visible) accumulator.allVisible += 1;
|
|
297
|
-
if (accumulator.allSamples.length < sampleLimit) accumulator.allSamples.push(renderable);
|
|
298
|
-
if ((renderable.lods?.length ?? 0) > 0) {
|
|
299
|
-
accumulator.lodCount += 1;
|
|
300
|
-
if (visible) accumulator.lodVisible += 1;
|
|
301
|
-
if (accumulator.lodSamples.length < sampleLimit) accumulator.lodSamples.push(renderable);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
const result: LodOcclusionWorldInspection[] = [];
|
|
305
|
-
for (let worldId = 0; worldId < worlds.length; worldId += 1) {
|
|
306
|
-
const world = worlds[worldId];
|
|
307
|
-
if (world === undefined) continue;
|
|
308
|
-
const accumulator = accumulators[worldId];
|
|
309
|
-
if (accumulator === undefined || accumulator.allCount === 0) {
|
|
310
|
-
result.push(
|
|
311
|
-
Object.freeze({ attachmentId: world.identity, rows: Object.freeze([]), attribution }),
|
|
312
|
-
);
|
|
313
|
-
continue;
|
|
314
|
-
}
|
|
315
|
-
const usesLod = accumulator.lodCount > 0;
|
|
316
|
-
const candidateCount = usesLod ? accumulator.lodCount : accumulator.allCount;
|
|
317
|
-
const visible = usesLod ? accumulator.lodVisible : accumulator.allVisible;
|
|
318
|
-
const samples = usesLod ? accumulator.lodSamples : accumulator.allSamples;
|
|
319
|
-
const first = samples[0];
|
|
320
|
-
const slot =
|
|
321
|
-
first === undefined
|
|
322
|
-
? undefined
|
|
323
|
-
: slots.get(worldEntityKey(worldKeys[first.worldId] ?? first.worldId, first.entityKey));
|
|
324
|
-
const row: LodOcclusionInspectionRow = {
|
|
325
|
-
root: {
|
|
326
|
-
guid: first === undefined ? 'none' : `asset-handle:${first.assetHandle}`,
|
|
327
|
-
sourceKey: `render-world:${world.identity}`,
|
|
328
|
-
},
|
|
329
|
-
view: {
|
|
330
|
-
attachmentId: world.identity,
|
|
331
|
-
cameraEntity: world === worlds[camera.worldId ?? 0] ? (camera.entityKey ?? 0) : 0,
|
|
332
|
-
viewRole: 'main',
|
|
333
|
-
viewGeneration: camera.historyVersion ?? 0,
|
|
334
|
-
},
|
|
335
|
-
slot: { primitiveSlot: slot?.slot ?? 0, slotGeneration: slot?.generation ?? 0 },
|
|
336
|
-
generation: frameId,
|
|
337
|
-
count: { candidates: candidateCount, visible, occluded: candidateCount - visible },
|
|
338
|
-
lodHistogram: [{ level: 0, count: candidateCount }],
|
|
339
|
-
queryLatencyUs: { median: 0, p95: 0, last: 0 },
|
|
340
|
-
pagePressure: query,
|
|
341
|
-
fallback,
|
|
342
|
-
degradation,
|
|
343
|
-
samples: samples.map((candidate, index) => ({
|
|
344
|
-
primitiveSlot:
|
|
345
|
-
slots.get(
|
|
346
|
-
worldEntityKey(worldKeys[candidate.worldId] ?? candidate.worldId, candidate.entityKey),
|
|
347
|
-
)?.slot ?? index,
|
|
348
|
-
level: 0,
|
|
349
|
-
visible: submitted.has(candidate),
|
|
350
|
-
})),
|
|
351
|
-
};
|
|
352
|
-
result.push(
|
|
353
|
-
Object.freeze({
|
|
354
|
-
attachmentId: world.identity,
|
|
355
|
-
rows: Object.freeze([row]),
|
|
356
|
-
attribution,
|
|
357
|
-
}),
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
return Object.freeze(
|
|
361
|
-
result.sort((left, right) => left.attachmentId.localeCompare(right.attachmentId)),
|
|
362
|
-
);
|
|
299
|
+
const stableMembership =
|
|
300
|
+
membership === undefined
|
|
301
|
+
? undefined
|
|
302
|
+
: membership.map((entry) => ({
|
|
303
|
+
...entry,
|
|
304
|
+
worldEntity: rebaseWorldEntity(entry.worldEntity),
|
|
305
|
+
}));
|
|
306
|
+
const stableDrawKeys =
|
|
307
|
+
stableMembership === undefined
|
|
308
|
+
? new Set(
|
|
309
|
+
[...drawKeys].map((key) => {
|
|
310
|
+
const parts = key.split(':');
|
|
311
|
+
if (parts.length !== 4) return key;
|
|
312
|
+
const transientWorldEntity = Number(parts[0]);
|
|
313
|
+
if (!Number.isFinite(transientWorldEntity)) return key;
|
|
314
|
+
return `${rebaseWorldEntity(transientWorldEntity)}:${parts[1]}:${parts[2]}:${parts[3]}`;
|
|
315
|
+
}),
|
|
316
|
+
)
|
|
317
|
+
: new Set(
|
|
318
|
+
stableMembership.map((entry) =>
|
|
319
|
+
gpuDrivenShadowDrawKey(
|
|
320
|
+
entry.worldEntity,
|
|
321
|
+
entry.materialHandle,
|
|
322
|
+
entry.drawItemIndex,
|
|
323
|
+
entry.passIndex,
|
|
324
|
+
),
|
|
325
|
+
),
|
|
326
|
+
);
|
|
327
|
+
return {
|
|
328
|
+
entityKeys: new Set([...entityKeys].map(rebaseWorldEntity)),
|
|
329
|
+
drawKeys: stableDrawKeys,
|
|
330
|
+
membership: stableMembership,
|
|
331
|
+
};
|
|
363
332
|
}
|
|
364
333
|
|
|
365
334
|
type TimingSessionHost = RenderSystemInternals & {
|
|
@@ -418,12 +387,6 @@ export interface RendererProducerRoot {
|
|
|
418
387
|
readonly disabledWork: 'zero' | 'lazy';
|
|
419
388
|
}
|
|
420
389
|
|
|
421
|
-
/** Device-bound post-process resources prepared off to the side of the active renderer. */
|
|
422
|
-
export interface RecoveryPostProcessResources {
|
|
423
|
-
readonly device: RhiDevice;
|
|
424
|
-
readonly paramsBuffers: Map<string, Buffer>;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
390
|
const PRODUCER_ROOT_MATRIX: readonly RendererProducerRoot[] = Object.freeze([
|
|
428
391
|
{
|
|
429
392
|
kind: 'backend-surface',
|
|
@@ -520,129 +483,6 @@ export interface RecoveryProductionEvidence {
|
|
|
520
483
|
};
|
|
521
484
|
}
|
|
522
485
|
|
|
523
|
-
/**
|
|
524
|
-
* Unified transparent-queue sub-sort covering all four
|
|
525
|
-
* {@link TransparentSortConfig} modes. Reorders the
|
|
526
|
-
* `queue === RenderQueue.Transparent` segment of the dispatch list;
|
|
527
|
-
* all other queue segments keep their relative order.
|
|
528
|
-
*
|
|
529
|
-
* | mode | primary key | secondary key | tertiary key |
|
|
530
|
-
* |:--:|:--|:--|:--|
|
|
531
|
-
* | 0 (LAYER_Z) | `layer` ASC | `posZ` ASC | `materialHandle` ASC |
|
|
532
|
-
* | 1 (LAYER_Y) | `layer` ASC | `-(posY - pivotY * sizeY)` ASC | `materialHandle` ASC |
|
|
533
|
-
* | 2 (LAYER_YZ) | `layer` ASC | `(posY - pivotY * sizeY) + yzAlpha * posZ` ASC | `materialHandle` ASC |
|
|
534
|
-
* | 3 (DISTANCE) | `-(dist² from camera)` ASC (back-to-front, layer ignored) | — |
|
|
535
|
-
*
|
|
536
|
-
* The `materialHandle` tertiary key for modes 0/1/2 groups same-material
|
|
537
|
-
* entries together whenever the primary+secondary sort values are equal
|
|
538
|
-
* (e.g. tilemap tiles in the same row/layer share `posY` in LAYER_Y mode).
|
|
539
|
-
* Consecutive same-material groups then collapse into fold buckets in the
|
|
540
|
-
* record-stage fold operator, significantly reducing draw call count for
|
|
541
|
-
* tilemap-heavy scenes.
|
|
542
|
-
*
|
|
543
|
-
* `posX/Y/Z` = translation column of the entity's world mat4 (indices 12/13/14).
|
|
544
|
-
* `pivotY` = `RenderableSnapshot.material.paramSnapshot.pivotAndSize[1]` (default 0.5).
|
|
545
|
-
* `sizeY` = length of the Y-axis column of the world mat4 (indices 4/5/6).
|
|
546
|
-
*/
|
|
547
|
-
function sortTransparentDispatch(
|
|
548
|
-
dispatch: DispatchEntry[],
|
|
549
|
-
world: World,
|
|
550
|
-
cameras: readonly CameraSnapshot[],
|
|
551
|
-
renderables: readonly RenderableSnapshot[],
|
|
552
|
-
): DispatchEntry[] {
|
|
553
|
-
const cfg = getTransparentSortConfig(world);
|
|
554
|
-
const mode = cfg.mode;
|
|
555
|
-
|
|
556
|
-
// Indices of Transparent-queue entries within the dispatch list.
|
|
557
|
-
const transparentSlots: number[] = [];
|
|
558
|
-
for (let i = 0; i < dispatch.length; i++) {
|
|
559
|
-
if (dispatch[i]?.queue === RenderQueue.Transparent) transparentSlots.push(i);
|
|
560
|
-
}
|
|
561
|
-
if (transparentSlots.length <= 1) return dispatch;
|
|
562
|
-
|
|
563
|
-
let sortedSlotOrder: number[];
|
|
564
|
-
|
|
565
|
-
if (mode === TRANSPARENT_SORT_MODE_DISTANCE) {
|
|
566
|
-
const camera = cameras[0];
|
|
567
|
-
if (camera === undefined) return dispatch;
|
|
568
|
-
const camPos = camera.position;
|
|
569
|
-
|
|
570
|
-
// Squared camera distance per entry (negated → ascending = back-to-front).
|
|
571
|
-
// D-3: world position = translation column of GlobalTransform.world (m[12,13,14]).
|
|
572
|
-
const negDistSq = (entry: DispatchEntry): number => {
|
|
573
|
-
const tx = renderables[entry.renderableIndex]?.transform;
|
|
574
|
-
if (tx === undefined) return 0;
|
|
575
|
-
const w = tx.world;
|
|
576
|
-
const dx = (w[12] ?? 0) - (camPos[0] ?? 0);
|
|
577
|
-
const dy = (w[13] ?? 0) - (camPos[1] ?? 0);
|
|
578
|
-
const dz = (w[14] ?? 0) - (camPos[2] ?? 0);
|
|
579
|
-
return -(dx * dx + dy * dy + dz * dz);
|
|
580
|
-
};
|
|
581
|
-
|
|
582
|
-
sortedSlotOrder = transparentSlots.slice().sort((a, b) => {
|
|
583
|
-
const da = negDistSq(dispatch[a] as DispatchEntry);
|
|
584
|
-
const db = negDistSq(dispatch[b] as DispatchEntry);
|
|
585
|
-
if (da < db) return -1;
|
|
586
|
-
if (da > db) return 1;
|
|
587
|
-
return 0;
|
|
588
|
-
});
|
|
589
|
-
} else {
|
|
590
|
-
// Modes 0/1/2: primary = layer ASC, secondary = mode-formula ASC.
|
|
591
|
-
// sizeY = length of the Y-axis column (col1 = indices 4,5,6) of the
|
|
592
|
-
// world mat4; rotation-invariant and handles flipV sign correctly.
|
|
593
|
-
const sortVal = (entry: DispatchEntry): number => {
|
|
594
|
-
const tx = renderables[entry.renderableIndex]?.transform;
|
|
595
|
-
const w = tx?.world;
|
|
596
|
-
const posY = (w?.[13] ?? 0) as number;
|
|
597
|
-
const posZ = (w?.[14] ?? 0) as number;
|
|
598
|
-
if (mode === TRANSPARENT_SORT_MODE_LAYER_Z) return posZ;
|
|
599
|
-
const mat = renderables[entry.renderableIndex]?.material;
|
|
600
|
-
// feat-20260625-refactor-sprite-as-transparent-mesh M3 / w15: post
|
|
601
|
-
// SpriteFieldsSnapshot ablation, pivot lives in paramSnapshot
|
|
602
|
-
// .pivotAndSize[0..1] (UBO-aligned vec4 slot 2, plan D-6). Non-sprite
|
|
603
|
-
// materials carry paramSnapshot=undefined and fall back to 0.5.
|
|
604
|
-
const pivotAndSize = mat?.paramSnapshot?.pivotAndSize as readonly number[] | undefined;
|
|
605
|
-
const pivotY = (pivotAndSize?.[1] ?? 0.5) as number;
|
|
606
|
-
const wy4 = (w?.[4] ?? 0) as number;
|
|
607
|
-
const wy5 = (w?.[5] ?? 1) as number;
|
|
608
|
-
const wy6 = (w?.[6] ?? 0) as number;
|
|
609
|
-
const sizeY = Math.sqrt(wy4 * wy4 + wy5 * wy5 + wy6 * wy6);
|
|
610
|
-
const footY = posY - pivotY * sizeY;
|
|
611
|
-
if (mode === TRANSPARENT_SORT_MODE_LAYER_Y) return -footY;
|
|
612
|
-
if (mode === TRANSPARENT_SORT_MODE_LAYER_YZ) return footY + cfg.yzAlpha * posZ;
|
|
613
|
-
// Defensive fallback for an unknown mode that slips past setTransparentSortConfig.
|
|
614
|
-
return posZ;
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
sortedSlotOrder = transparentSlots.slice().sort((a, b) => {
|
|
618
|
-
const da = dispatch[a] as DispatchEntry;
|
|
619
|
-
const db = dispatch[b] as DispatchEntry;
|
|
620
|
-
const la = da.layer;
|
|
621
|
-
const lb = db.layer;
|
|
622
|
-
if (la !== lb) return la - lb;
|
|
623
|
-
const va = sortVal(da);
|
|
624
|
-
const vb = sortVal(db);
|
|
625
|
-
if (va < vb) return -1;
|
|
626
|
-
if (va > vb) return 1;
|
|
627
|
-
// Tertiary tiebreaker: group same-materialHandle entries together so
|
|
628
|
-
// fold-eligible consecutive runs form. Entries at equal (layer,
|
|
629
|
-
// sortVal) — e.g. tilemap tiles in the same row under LAYER_Y — are
|
|
630
|
-
// depth-equivalent; reordering them by material does not change the
|
|
631
|
-
// visual result but maximises fold-bucket width.
|
|
632
|
-
return da.materialHandle - db.materialHandle;
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
// Scatter the reordered Transparent entries back into their original slots.
|
|
637
|
-
const result = dispatch.slice();
|
|
638
|
-
for (let k = 0; k < transparentSlots.length; k++) {
|
|
639
|
-
const targetSlot = transparentSlots[k] as number;
|
|
640
|
-
const sourceSlot = sortedSlotOrder[k] as number;
|
|
641
|
-
result[targetSlot] = dispatch[sourceSlot] as DispatchEntry;
|
|
642
|
-
}
|
|
643
|
-
return result;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
486
|
/**
|
|
647
487
|
* Engine-internal Extract / Prepare / Record driver; constructed by createRenderer.
|
|
648
488
|
*
|
|
@@ -660,6 +500,9 @@ function sortTransparentDispatch(
|
|
|
660
500
|
* whose shader identity is `forgeax::default-standard-pbr`).
|
|
661
501
|
*/
|
|
662
502
|
export interface RenderSystem {
|
|
503
|
+
bounds(world: World, entity: number): RenderSceneBounds | undefined;
|
|
504
|
+
/** Complete explicit SSR capability preparation before drawing a device generation. */
|
|
505
|
+
initializeSsr(device?: RhiDevice): Promise<void>;
|
|
663
506
|
/** Returns true only when this invocation reached queue submission. */
|
|
664
507
|
draw(
|
|
665
508
|
worlds: readonly World[],
|
|
@@ -677,7 +520,7 @@ export interface RenderSystem {
|
|
|
677
520
|
/** Prepare a detached graph candidate without entering the frame record path. */
|
|
678
521
|
prepareRecoveryGraphCandidate(
|
|
679
522
|
runtime: RecoveryGraphCandidateRuntime,
|
|
680
|
-
):
|
|
523
|
+
): RecoveryGraphCandidatePreparation;
|
|
681
524
|
/** Finish and submit detached candidate setup, never a frame receipt. */
|
|
682
525
|
submitCandidateSetup(
|
|
683
526
|
candidate: RecoveryGraphCandidate,
|
|
@@ -703,6 +546,8 @@ export interface RenderSystem {
|
|
|
703
546
|
readonly pipelineDispatchCounts: {
|
|
704
547
|
readonly unlit: number;
|
|
705
548
|
};
|
|
549
|
+
/** Renderer-owned source for explicit large instance collections. */
|
|
550
|
+
readonly instances: InstanceCollectionStore;
|
|
706
551
|
/** Detached residency and upload facts for explicit instance collections. */
|
|
707
552
|
readonly instanceCollectionsInspection: readonly InstanceCollectionInspection[];
|
|
708
553
|
/**
|
|
@@ -717,11 +562,17 @@ export interface RenderSystem {
|
|
|
717
562
|
readonly reflectionProbes: ReflectionProbeInspection;
|
|
718
563
|
/** Live producer/RHI/temporal receipts projected through SSR admission. */
|
|
719
564
|
readonly ssrDependencies: SsrDependenciesInspection;
|
|
565
|
+
/** Live SSR spatial admission and bounded graph/history projection. */
|
|
566
|
+
readonly ssr: SsrSpatialInspection;
|
|
720
567
|
/** Producer completion fence included in the public FrameReceipt. */
|
|
721
568
|
readonly reflectionFallbackCompletion: Promise<void> | undefined;
|
|
722
569
|
/** True while a progressive CubeCamera candidate still owns unfinished faces. */
|
|
723
570
|
isCubeCapturePending(target: RenderTarget): boolean;
|
|
724
571
|
readonly environment: EnvironmentInspection;
|
|
572
|
+
/** Detached auto-exposure state published after a successful frame submit. */
|
|
573
|
+
readonly autoExposure: AutoExposureInspection | undefined;
|
|
574
|
+
/** Detached Standard LUT state published after a successful frame submit. */
|
|
575
|
+
readonly standardLut: StandardLutInspection;
|
|
725
576
|
readonly temporal: TemporalInspection;
|
|
726
577
|
readonly bloom: BloomInspection;
|
|
727
578
|
readonly motionBlurInspection: MotionBlurInspection | undefined;
|
|
@@ -756,6 +607,10 @@ export interface RenderSystem {
|
|
|
756
607
|
readonly lastSuccessfulCameraAntialias: CameraSnapshot['antialias'] | undefined;
|
|
757
608
|
/** Detached compiled-graph facts used by the renderer inspection owner. */
|
|
758
609
|
readonly perFrameGraphInfo: CompiledRenderGraphInfo | undefined;
|
|
610
|
+
/** Detached feature signature/compile/lifetime counters. */
|
|
611
|
+
readonly featureGraphInspection: import('./inspection-types').RenderFeatureGraphInspection;
|
|
612
|
+
/** Detached material texture-source probe counters from the last extract. */
|
|
613
|
+
readonly materialTextureSources: MaterialTextureSourceInspection;
|
|
759
614
|
/** Production-owner recovery facts used by Renderer.inspect(). */
|
|
760
615
|
readonly recoveryEvidence: RecoveryProductionEvidence;
|
|
761
616
|
/**
|
|
@@ -878,13 +733,6 @@ function makePreparedPipelinePendingError(): RhiError {
|
|
|
878
733
|
});
|
|
879
734
|
}
|
|
880
735
|
|
|
881
|
-
/** The single Points/Lines owner’s staged device-generation handoff. */
|
|
882
|
-
export interface RecoveryPointsLinesCandidate {
|
|
883
|
-
createRecoveryRoot(scope: DeviceScope): LifecycleResourceSpec<unknown>;
|
|
884
|
-
publish(): void;
|
|
885
|
-
release(): void;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
736
|
function preparationFailureFrom(error: unknown): MeshMaterialBindingPreparationFailure | undefined {
|
|
889
737
|
if (typeof error !== 'object' || error === null) return undefined;
|
|
890
738
|
const value = error as {
|
|
@@ -912,58 +760,6 @@ function preparationFailureFrom(error: unknown): MeshMaterialBindingPreparationF
|
|
|
912
760
|
};
|
|
913
761
|
}
|
|
914
762
|
|
|
915
|
-
/** Candidate-only device/runtime inputs used by the recovery prepare seam. */
|
|
916
|
-
export interface RecoveryGraphCandidateRuntime {
|
|
917
|
-
readonly internals: RenderSystemInternals;
|
|
918
|
-
readonly pipelineState: PipelineState;
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
/** Detached graph state prepared on a replacement device, before publication. */
|
|
922
|
-
export interface RecoveryGraphCandidate {
|
|
923
|
-
readonly frameState: RenderFrameState;
|
|
924
|
-
readonly setupWorks: readonly MipmapEncoderWork[];
|
|
925
|
-
readonly device: RhiDevice;
|
|
926
|
-
readonly generation: number;
|
|
927
|
-
readonly gpuDrivenProduction?: GpuDrivenProduction;
|
|
928
|
-
readonly gpuDrivenScene?: PersistentGpuDrivenCandidate;
|
|
929
|
-
/** Staged CPU-expanded Points/Lines buffers owned by the same RenderSystem. */
|
|
930
|
-
readonly pointsLines?: RecoveryPointsLinesCandidate;
|
|
931
|
-
readonly featureHost?: RenderFeatureHost;
|
|
932
|
-
readonly featureGpuWork?: RenderFeatureGpuWorkOwner;
|
|
933
|
-
readonly featureGraphCandidate?: RenderFeatureGraphCandidate;
|
|
934
|
-
readonly postProcessPipelines?: ReadonlyMap<string, RenderPipeline>;
|
|
935
|
-
readonly recoveryReadiness: RecoveryPipelineReadiness;
|
|
936
|
-
/** Release all candidate roots before publication; safe to call repeatedly. */
|
|
937
|
-
readonly release: () => void;
|
|
938
|
-
/** Transfer candidate-root ownership to the published RenderSystem. */
|
|
939
|
-
readonly markPublished: () => void;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
/** Candidate setup completion; completion is bounded by the recovery owner. */
|
|
943
|
-
export interface RecoveryGraphSetupSubmission {
|
|
944
|
-
readonly completion?: PromiseLike<unknown>;
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
export type RecoveryGraphCandidatePreparation =
|
|
948
|
-
| { readonly kind: 'no-seed' }
|
|
949
|
-
| { readonly kind: 'ready'; readonly candidate: RecoveryGraphCandidate }
|
|
950
|
-
| { readonly kind: 'failed'; readonly reason: string; readonly cause?: unknown };
|
|
951
|
-
|
|
952
|
-
/** Explicit candidate-owned inputs for lifecycle-root preparation. */
|
|
953
|
-
export interface RecoveryRootRuntime {
|
|
954
|
-
readonly scope: DeviceScope;
|
|
955
|
-
readonly device: RhiDevice;
|
|
956
|
-
readonly gpuStore: GpuResidencyCache;
|
|
957
|
-
readonly graphCandidate?: RecoveryGraphCandidate | undefined;
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
/** Candidate roots plus the one synchronous owner switch at publication. */
|
|
961
|
-
export interface RecoveryRootBundle {
|
|
962
|
-
readonly roots: readonly LifecycleResourceSpec<unknown>[];
|
|
963
|
-
publish(): void;
|
|
964
|
-
discard(): void;
|
|
965
|
-
}
|
|
966
|
-
|
|
967
763
|
/**
|
|
968
764
|
* Project the producer-owned material and GPU store state into the one
|
|
969
765
|
* renderer observation surface. This is intentionally recomputed from the
|
|
@@ -1088,42 +884,37 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1088
884
|
let releaseProfilerCatalog =
|
|
1089
885
|
phaseCatalogRegistration?.ok === true ? phaseCatalogRegistration.value : undefined;
|
|
1090
886
|
let preparedWorlds: readonly World[] = [];
|
|
1091
|
-
|
|
887
|
+
const resolveFeatureNoise = createFeatureNoiseResolver({
|
|
888
|
+
scope: internals.deviceScope,
|
|
889
|
+
getDevice: () => internals.device,
|
|
890
|
+
onError: (error) => internals.errorRegistry.fire(error),
|
|
891
|
+
});
|
|
892
|
+
let preparedFeatureSkylightResources: SkylightBindGroupResources | undefined;
|
|
893
|
+
const dynamicGeometryFrames = createDynamicGeometryFrameBindings();
|
|
1092
894
|
let latestCamera: CameraSnapshot | undefined;
|
|
1093
895
|
const pointsLinesOwner = new StandardPointsLinesOwner(internals);
|
|
1094
|
-
const instanceCollections = new
|
|
896
|
+
const instanceCollections = new InstanceCollectionStore();
|
|
1095
897
|
const reflectionProbeOwner = new ReflectionProbeRecordOwner(internals);
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
898
|
+
const ssrFormatReceipts = new WeakMap<
|
|
899
|
+
RhiDevice,
|
|
900
|
+
import('@forgeax/engine-rhi').RhiTextureFormatCapabilityReceipt
|
|
901
|
+
>();
|
|
1099
902
|
let ssrFallbackGeneration: number | undefined;
|
|
1100
|
-
const ensureSsrFormatProbe = (): void => {
|
|
1101
|
-
if (internals.ssrIdentity === undefined) return;
|
|
1102
|
-
const generation = internals.deviceScope.generation;
|
|
903
|
+
const ensureSsrFormatProbe = async (device = internals.device): Promise<void> => {
|
|
1103
904
|
if (
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
typeof internals.device.probeTextureFormatCapability !== 'function'
|
|
1108
|
-
) {
|
|
905
|
+
internals.ssrIdentity === undefined ||
|
|
906
|
+
typeof device.probeTextureFormatCapability !== 'function'
|
|
907
|
+
)
|
|
1109
908
|
return;
|
|
909
|
+
// RHI memoizes the probe per physical device. Retain the detached candidate
|
|
910
|
+
// receipt without publishing it: inspection selects only the active device.
|
|
911
|
+
// A failed/late recovery therefore cannot overwrite the active generation.
|
|
912
|
+
try {
|
|
913
|
+
const result = await device.probeTextureFormatCapability();
|
|
914
|
+
if (result.ok) ssrFormatReceipts.set(device, result.value);
|
|
915
|
+
} catch {
|
|
916
|
+
// Missing capability remains an explicit fallback-only admission.
|
|
1110
917
|
}
|
|
1111
|
-
ssrFormatProbeGeneration = generation;
|
|
1112
|
-
const device = internals.device;
|
|
1113
|
-
ssrFormatProbe = device
|
|
1114
|
-
.probeTextureFormatCapability()
|
|
1115
|
-
.then((result) => {
|
|
1116
|
-
if (internals.device !== device || internals.deviceScope.generation !== generation) return;
|
|
1117
|
-
ssrFormatReceipt = result.ok ? result.value : undefined;
|
|
1118
|
-
})
|
|
1119
|
-
.catch(() => {
|
|
1120
|
-
if (internals.device === device && internals.deviceScope.generation === generation) {
|
|
1121
|
-
ssrFormatReceipt = undefined;
|
|
1122
|
-
}
|
|
1123
|
-
})
|
|
1124
|
-
.finally(() => {
|
|
1125
|
-
ssrFormatProbe = undefined;
|
|
1126
|
-
});
|
|
1127
918
|
};
|
|
1128
919
|
const cubeCaptureScheduler = createCubeCaptureScheduler({ maxFacesPerFrame: 1 });
|
|
1129
920
|
const cubeCaptureState: CubeCaptureGraphState = { work: [] };
|
|
@@ -1134,7 +925,6 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1134
925
|
internals.gpuStore.invalidateMesh(handle, preparedWorlds[worldId] ?? worldId);
|
|
1135
926
|
},
|
|
1136
927
|
instanceCollections,
|
|
1137
|
-
getSkinPaletteAllocator: () => internals.getPipelineState()?.skinPaletteAllocator ?? null,
|
|
1138
928
|
});
|
|
1139
929
|
let environmentLifecycle = new EnvironmentLifecycle(internals.deviceScope);
|
|
1140
930
|
const transmissionAdmission = new TransmissionCandidateAdmission();
|
|
@@ -1278,7 +1068,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1278
1068
|
}),
|
|
1279
1069
|
),
|
|
1280
1070
|
} satisfies import('./pipeline-builder').PipelineBuilderShaderModuleFactory);
|
|
1281
|
-
let
|
|
1071
|
+
let gpuDrivenRecoveryCount = 0;
|
|
1072
|
+
let gpuDrivenProduction = createGpuDrivenOwner(
|
|
1073
|
+
internals.device,
|
|
1074
|
+
gpuDrivenShaderFactory,
|
|
1075
|
+
gpuDrivenRecoveryCount,
|
|
1076
|
+
);
|
|
1282
1077
|
let occlusionRuntime: OcclusionRenderRuntime | undefined = new OcclusionRenderRuntime(
|
|
1283
1078
|
internals.device,
|
|
1284
1079
|
persistentRenderScene.visibilityFacetStore(),
|
|
@@ -1346,6 +1141,13 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1346
1141
|
const frameState: RenderFrameState = {
|
|
1347
1142
|
frameNumber: 0,
|
|
1348
1143
|
reflectionFallbackDemand: false,
|
|
1144
|
+
ssrRequested: false,
|
|
1145
|
+
ssrSpatialAdmission: undefined,
|
|
1146
|
+
ssrHistoryOwner: undefined,
|
|
1147
|
+
ssrHistoryCandidate: undefined,
|
|
1148
|
+
ssrTemporalParamsPayload: new Uint8Array(32),
|
|
1149
|
+
ssrLastCameraEntity: undefined,
|
|
1150
|
+
ssrLastHistoryVersion: undefined,
|
|
1349
1151
|
graphGeneration: 0,
|
|
1350
1152
|
successfulTemporalFrameIndex: 0,
|
|
1351
1153
|
lastSuccessfulBloom: 'off',
|
|
@@ -1376,6 +1178,14 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1376
1178
|
reflectionFallbackObservationSource: undefined,
|
|
1377
1179
|
lastSuccessfulCameraAntialias: undefined,
|
|
1378
1180
|
temporalGpuState: undefined,
|
|
1181
|
+
autoExposureGpuResources: undefined,
|
|
1182
|
+
pendingAutoExposureGpuResources: undefined,
|
|
1183
|
+
autoExposureState: undefined,
|
|
1184
|
+
pendingAutoExposureState: undefined,
|
|
1185
|
+
standardLutGpuResources: undefined,
|
|
1186
|
+
pendingStandardLutGpuResources: undefined,
|
|
1187
|
+
standardLutState: createStandardLutState({ deviceEpoch: internals.deviceScope.generation }),
|
|
1188
|
+
pendingStandardLutState: undefined,
|
|
1379
1189
|
activeTemporalGpuState: undefined,
|
|
1380
1190
|
retiringTemporalGpuStates: new Set(),
|
|
1381
1191
|
lastSuccessfulTemporalView: undefined,
|
|
@@ -1385,7 +1195,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1385
1195
|
currentDirectionalShadowView: null,
|
|
1386
1196
|
currentSpotShadowView: null,
|
|
1387
1197
|
instanceBuffers: new Map(),
|
|
1388
|
-
|
|
1198
|
+
instanceCollections,
|
|
1389
1199
|
instanceBufferChunks: new Map(),
|
|
1390
1200
|
probeBlendBuffers: new Map(),
|
|
1391
1201
|
probeBlendRecordBufferCapacity: 0,
|
|
@@ -1437,7 +1247,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1437
1247
|
// explicit texture/sampler handles resolved to resident GPU resources.
|
|
1438
1248
|
materialBgAssemblyCache: new Map(),
|
|
1439
1249
|
// singleton material cache (flat Map<variant, BindGroup>; D-6).
|
|
1440
|
-
|
|
1250
|
+
shadowMaterialBindGroups: new WeakMap(),
|
|
1441
1251
|
// post-process bind group cache (bloom / fxaa / ssao): identity-keyed
|
|
1442
1252
|
// WeakMap chain so resize-retired transient targets rebuild automatically.
|
|
1443
1253
|
postProcessBgCache: new WeakMap(),
|
|
@@ -1468,6 +1278,25 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1468
1278
|
// tiles until the first frame with a castShadow spot (AC-03).
|
|
1469
1279
|
spotShadowSnapshots: [],
|
|
1470
1280
|
};
|
|
1281
|
+
const resolveSsrDependencies = (requested: boolean): SsrDependenciesInspection => {
|
|
1282
|
+
// Explicit SSR capability preparation belongs to initialization. Inspection
|
|
1283
|
+
// only projects receipts and never starts work or creates image history.
|
|
1284
|
+
const owner = reflectionProbeOwner.inspect();
|
|
1285
|
+
const temporal =
|
|
1286
|
+
frameState.lastSuccessfulTemporalView === undefined
|
|
1287
|
+
? undefined
|
|
1288
|
+
: ({
|
|
1289
|
+
successfulSubmit: true,
|
|
1290
|
+
generation: frameState.lastSuccessfulTemporalView.input.deviceGeneration,
|
|
1291
|
+
} as const);
|
|
1292
|
+
return projectSsrDependencies({
|
|
1293
|
+
requested,
|
|
1294
|
+
identity: internals.ssrIdentity,
|
|
1295
|
+
reflectionFallback: owner.reflectionFallback,
|
|
1296
|
+
format: ssrFormatReceipts.get(internals.device),
|
|
1297
|
+
temporal,
|
|
1298
|
+
});
|
|
1299
|
+
};
|
|
1471
1300
|
let directFrameId = 0;
|
|
1472
1301
|
let submittedFrameCount = 0;
|
|
1473
1302
|
let lastSubmittedGeneration: number | undefined;
|
|
@@ -1475,6 +1304,122 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1475
1304
|
let lastDirectionalShadowCandidate: 'accepted' | 'failed' = 'failed';
|
|
1476
1305
|
let lastDirectionalShadowError: DirectionalShadowInspectionSource['error'];
|
|
1477
1306
|
|
|
1307
|
+
/**
|
|
1308
|
+
* Stage the detached auto/LUT facts beside the GPU candidates already owned
|
|
1309
|
+
* by RenderFrameState. The typed graph promotes both records only after its
|
|
1310
|
+
* single finish/submit transaction succeeds; no side registry or compile
|
|
1311
|
+
* callback can publish a value early.
|
|
1312
|
+
*/
|
|
1313
|
+
function stageLiveFeatureState(camera: CameraSnapshot | undefined, deltaTime: number): void {
|
|
1314
|
+
frameState.pendingAutoExposureState = undefined;
|
|
1315
|
+
frameState.pendingStandardLutState = undefined;
|
|
1316
|
+
const output = camera?.output;
|
|
1317
|
+
if (output === undefined) return;
|
|
1318
|
+
|
|
1319
|
+
const publicFrameId =
|
|
1320
|
+
(internals as RenderSystemInternals & { readonly observationFrameId?: number })
|
|
1321
|
+
.observationFrameId ?? frameState.frameNumber;
|
|
1322
|
+
const targetGeneration = Math.max(1, camera?.historyVersion ?? 0);
|
|
1323
|
+
const deviceEpoch = internals.deviceScope.generation;
|
|
1324
|
+
|
|
1325
|
+
if (
|
|
1326
|
+
output.exposure.kind === 'auto' &&
|
|
1327
|
+
(frameState.pendingAutoExposureGpuResources !== undefined ||
|
|
1328
|
+
frameState.autoExposureGpuResources !== undefined)
|
|
1329
|
+
) {
|
|
1330
|
+
let state = frameState.autoExposureState;
|
|
1331
|
+
if (state === undefined || state.fallback !== output.exposure.fallback) {
|
|
1332
|
+
const created = createAutoExposureState({
|
|
1333
|
+
fallback: output.exposure.fallback,
|
|
1334
|
+
targetGeneration,
|
|
1335
|
+
deviceEpoch,
|
|
1336
|
+
frameId: publicFrameId,
|
|
1337
|
+
});
|
|
1338
|
+
if (!created.ok) {
|
|
1339
|
+
internals.errorRegistry.fire(created.error);
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
state = created.value;
|
|
1343
|
+
} else if (state.targetGeneration !== targetGeneration || state.deviceEpoch !== deviceEpoch) {
|
|
1344
|
+
state = resetAutoExposureState(state, 'camera-change', {
|
|
1345
|
+
targetGeneration,
|
|
1346
|
+
deviceEpoch,
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
const resources =
|
|
1350
|
+
frameState.pendingAutoExposureGpuResources ?? frameState.autoExposureGpuResources;
|
|
1351
|
+
if (resources !== undefined) {
|
|
1352
|
+
const parameterWrite = writeAutoExposureParameters(resources, {
|
|
1353
|
+
compensationEv: output.exposure.compensationEv,
|
|
1354
|
+
rangeMinEv: output.exposure.rangeEv[0],
|
|
1355
|
+
rangeMaxEv: output.exposure.rangeEv[1],
|
|
1356
|
+
upRate: output.exposure.rates[0],
|
|
1357
|
+
downRate: output.exposure.rates[1],
|
|
1358
|
+
deltaTime,
|
|
1359
|
+
fallback: output.exposure.fallback,
|
|
1360
|
+
generation: state.targetGeneration,
|
|
1361
|
+
});
|
|
1362
|
+
if (!parameterWrite.ok) {
|
|
1363
|
+
internals.errorRegistry.fire(parameterWrite.error as RhiError);
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
// The GPU adapt pass owns the numeric candidate. CPU staging carries
|
|
1368
|
+
// only the generation/transaction facts needed for submit publication.
|
|
1369
|
+
frameState.pendingAutoExposureState = Object.freeze({
|
|
1370
|
+
state,
|
|
1371
|
+
generation: state.targetGeneration,
|
|
1372
|
+
deviceEpoch: state.deviceEpoch,
|
|
1373
|
+
frameId: publicFrameId,
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
let lutState = frameState.standardLutState;
|
|
1378
|
+
if (lutState.targetGeneration !== targetGeneration || lutState.deviceEpoch !== deviceEpoch) {
|
|
1379
|
+
lutState = resetStandardLutState(lutState, 'device-recovered', {
|
|
1380
|
+
targetGeneration,
|
|
1381
|
+
deviceEpoch,
|
|
1382
|
+
});
|
|
1383
|
+
frameState.standardLutState = lutState;
|
|
1384
|
+
}
|
|
1385
|
+
const wantsLut = output.colorLutStrength > 0 && output.colorLut > 0;
|
|
1386
|
+
const lutResources =
|
|
1387
|
+
frameState.pendingStandardLutGpuResources ?? frameState.standardLutGpuResources;
|
|
1388
|
+
if (wantsLut && lutResources !== undefined) {
|
|
1389
|
+
const prepared = prepareStandardLutCandidate(lutState, {
|
|
1390
|
+
// sourceKey is the Catalog-owned identity returned by the same
|
|
1391
|
+
// preparation that built the live LUT bind group; numeric handles do
|
|
1392
|
+
// not cross the inspection boundary.
|
|
1393
|
+
resident: lutResources.sourceKey,
|
|
1394
|
+
sourceKey: lutResources.sourceKey,
|
|
1395
|
+
generation: lutState.targetGeneration,
|
|
1396
|
+
deviceEpoch: lutState.deviceEpoch,
|
|
1397
|
+
frameId: publicFrameId,
|
|
1398
|
+
});
|
|
1399
|
+
if (prepared.ok) {
|
|
1400
|
+
frameState.pendingStandardLutState = Object.freeze({
|
|
1401
|
+
state: lutState,
|
|
1402
|
+
candidate: prepared.value,
|
|
1403
|
+
remove: false,
|
|
1404
|
+
targetGeneration,
|
|
1405
|
+
deviceEpoch,
|
|
1406
|
+
});
|
|
1407
|
+
}
|
|
1408
|
+
} else if (!wantsLut && lutState.resident !== null) {
|
|
1409
|
+
frameState.pendingStandardLutState = Object.freeze({
|
|
1410
|
+
state: lutState,
|
|
1411
|
+
remove: true,
|
|
1412
|
+
targetGeneration,
|
|
1413
|
+
deviceEpoch,
|
|
1414
|
+
});
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
function discardLiveFeatureState(): void {
|
|
1419
|
+
frameState.pendingAutoExposureState = undefined;
|
|
1420
|
+
frameState.pendingStandardLutState = undefined;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1478
1423
|
function beginProfilePhase(session: RecorderSession | undefined, phase: RenderPhase): boolean {
|
|
1479
1424
|
if (session === undefined) return false;
|
|
1480
1425
|
try {
|
|
@@ -1706,22 +1651,21 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1706
1651
|
const getPostProcessPipeline = (
|
|
1707
1652
|
id: string,
|
|
1708
1653
|
bgl: BindGroupLayout,
|
|
1709
|
-
|
|
1654
|
+
colorFormats: readonly GPUTextureFormat[],
|
|
1710
1655
|
entryOverride?: PostProcessShaderEntry,
|
|
1711
1656
|
): RenderPipeline | null => {
|
|
1712
1657
|
const entry = entryOverride ?? lookupPostProcess(id);
|
|
1713
1658
|
if (entry === undefined) return null;
|
|
1714
1659
|
const signature = postProcessShaderEntrySignature(entry);
|
|
1715
|
-
const key = `${id}|${
|
|
1660
|
+
const key = `${id}|${colorFormats.join(',')}|${signature}`;
|
|
1716
1661
|
const cached = postProcessPipelineCache.get(key);
|
|
1717
1662
|
if (cached !== undefined) return cached;
|
|
1718
|
-
internals.recoveryColdWorkGuard?.notePipelineColdWork();
|
|
1719
1663
|
const factory = internals.buildPostProcessPipeline;
|
|
1720
1664
|
if (factory === undefined) return null;
|
|
1721
1665
|
const built = factory(
|
|
1722
1666
|
entry,
|
|
1723
1667
|
bgl,
|
|
1724
|
-
|
|
1668
|
+
colorFormats,
|
|
1725
1669
|
postProcessShaderPipelineLabel(id, entry.source),
|
|
1726
1670
|
);
|
|
1727
1671
|
if (built === null) return null;
|
|
@@ -1892,193 +1836,18 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1892
1836
|
createBindGroup: 0,
|
|
1893
1837
|
keys: [],
|
|
1894
1838
|
};
|
|
1895
|
-
type PreparedResolverCaches = {
|
|
1896
|
-
readonly preparedPipelineIds: WeakMap<object, string>;
|
|
1897
|
-
readonly preparedMaterialPipelineShaders: WeakMap<object, string>;
|
|
1898
|
-
readonly preparedGroup0Pipelines: WeakSet<object>;
|
|
1899
|
-
readonly preparedViewOnlyPipelines: WeakSet<object>;
|
|
1900
|
-
readonly preparedRenderMaterialPipelines: WeakSet<object>;
|
|
1901
|
-
readonly preparedAssetHandles: WeakMap<World, Map<string, number>>;
|
|
1902
|
-
};
|
|
1903
|
-
const createPreparedResolverCaches = (): PreparedResolverCaches => ({
|
|
1904
|
-
preparedPipelineIds: new WeakMap(),
|
|
1905
|
-
preparedMaterialPipelineShaders: new WeakMap(),
|
|
1906
|
-
preparedGroup0Pipelines: new WeakSet(),
|
|
1907
|
-
preparedViewOnlyPipelines: new WeakSet(),
|
|
1908
|
-
preparedRenderMaterialPipelines: new WeakSet(),
|
|
1909
|
-
preparedAssetHandles: new WeakMap(),
|
|
1910
|
-
});
|
|
1911
1839
|
const activePreparedResolverCaches = createPreparedResolverCaches();
|
|
1912
|
-
const preparedHandle = <Brand extends string>(
|
|
1913
|
-
runtime: RenderSystemInternals,
|
|
1914
|
-
caches: PreparedResolverCaches,
|
|
1915
|
-
world: World,
|
|
1916
|
-
guid: string,
|
|
1917
|
-
brand: Brand,
|
|
1918
|
-
): Handle<Brand, 'shared'> | undefined => {
|
|
1919
|
-
let handles = caches.preparedAssetHandles.get(world);
|
|
1920
|
-
if (handles === undefined) {
|
|
1921
|
-
handles = new Map();
|
|
1922
|
-
caches.preparedAssetHandles.set(world, handles);
|
|
1923
|
-
}
|
|
1924
|
-
const key = `${brand}:${guid.toLowerCase()}`;
|
|
1925
|
-
const cached = handles.get(key);
|
|
1926
|
-
if (cached !== undefined) return cached as Handle<Brand, 'shared'>;
|
|
1927
|
-
const asset = runtime.assets.lookup(guid);
|
|
1928
|
-
if (asset === undefined) return undefined;
|
|
1929
|
-
const handle = world.allocSharedRef(brand, asset);
|
|
1930
|
-
handles.set(key, handle as number);
|
|
1931
|
-
return handle;
|
|
1932
|
-
};
|
|
1933
|
-
const preparedMaterialBindings = (
|
|
1934
|
-
runtime: RenderSystemInternals,
|
|
1935
|
-
caches: PreparedResolverCaches,
|
|
1936
|
-
worlds: readonly World[],
|
|
1937
|
-
materialShaderId: string,
|
|
1938
|
-
worldIndex: number,
|
|
1939
|
-
materialGuid: string,
|
|
1940
|
-
layout: BindGroupLayout,
|
|
1941
|
-
) => {
|
|
1942
|
-
const world = worlds[worldIndex];
|
|
1943
|
-
const material = runtime.assets.lookup(materialGuid) as MaterialAsset | undefined;
|
|
1944
|
-
const pipelineState = runtime.getPipelineState();
|
|
1945
|
-
if (world === undefined || material?.kind !== 'material' || pipelineState === null) {
|
|
1946
|
-
return err(new Error('prepared material asset is unavailable'));
|
|
1947
|
-
}
|
|
1948
|
-
const schema = runtime.getParamSchema?.(materialShaderId) ?? [];
|
|
1949
|
-
const values = material.values ?? {};
|
|
1950
|
-
const derived = derive(schema);
|
|
1951
|
-
const fields = [...derived.textureFieldNames];
|
|
1952
|
-
let buffer: Buffer | undefined;
|
|
1953
|
-
let payloadByteLength = 0;
|
|
1954
|
-
if (derived.uboLayout.totalBytes > 0) {
|
|
1955
|
-
const payload = new Uint8Array(Math.max(16, derived.uboLayout.totalBytes));
|
|
1956
|
-
applyParamSnapshotToUbo(
|
|
1957
|
-
payload,
|
|
1958
|
-
schema,
|
|
1959
|
-
values as Readonly<Record<string, number | readonly number[]>>,
|
|
1960
|
-
);
|
|
1961
|
-
const created = runtime.device.createBuffer({
|
|
1962
|
-
label: `prepared-material:${materialGuid}`,
|
|
1963
|
-
size: payload.byteLength,
|
|
1964
|
-
usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
|
|
1965
|
-
});
|
|
1966
|
-
if (!created.ok) return created;
|
|
1967
|
-
buffer = created.value;
|
|
1968
|
-
payloadByteLength = payload.byteLength;
|
|
1969
|
-
const written = runtime.device.queue.writeBuffer(buffer, 0, payload);
|
|
1970
|
-
if (!written.ok) {
|
|
1971
|
-
runtime.device.destroyBuffer(buffer);
|
|
1972
|
-
return written;
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
const textureResources: Array<{
|
|
1976
|
-
sampler: import('@forgeax/engine-rhi').Sampler;
|
|
1977
|
-
view: import('@forgeax/engine-rhi').TextureView;
|
|
1978
|
-
}> = [];
|
|
1979
|
-
for (let index = 0; index < fields.length; index += 1) {
|
|
1980
|
-
const field = fields[index];
|
|
1981
|
-
const value = field === undefined ? undefined : values[field];
|
|
1982
|
-
const textureValue =
|
|
1983
|
-
typeof value === 'object' && value !== null && 'texture' in value
|
|
1984
|
-
? (value as MaterialTextureValue)
|
|
1985
|
-
: undefined;
|
|
1986
|
-
let sampler = pipelineState.defaultSampler;
|
|
1987
|
-
if (textureValue?.sampler !== undefined) {
|
|
1988
|
-
const handle = preparedHandle(
|
|
1989
|
-
runtime,
|
|
1990
|
-
caches,
|
|
1991
|
-
world,
|
|
1992
|
-
String(textureValue.sampler),
|
|
1993
|
-
'SamplerAsset',
|
|
1994
|
-
);
|
|
1995
|
-
if (handle !== undefined) {
|
|
1996
|
-
const asset = resolveAssetHandle<SamplerAsset>(world, handle);
|
|
1997
|
-
if (asset.ok) {
|
|
1998
|
-
const resident = runtime.gpuStore.ensureSamplerResident(handle, asset.value, world);
|
|
1999
|
-
if (resident.ok) sampler = resident.value;
|
|
2000
|
-
}
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
|
-
let view = pipelineState.defaultWhiteTextureView;
|
|
2004
|
-
if (textureValue !== undefined) {
|
|
2005
|
-
const handle = preparedHandle(
|
|
2006
|
-
runtime,
|
|
2007
|
-
caches,
|
|
2008
|
-
world,
|
|
2009
|
-
String(textureValue.texture),
|
|
2010
|
-
'TextureAsset',
|
|
2011
|
-
);
|
|
2012
|
-
if (handle !== undefined) {
|
|
2013
|
-
view = residentTextureView(world, runtime.gpuStore, runtime, handle) ?? view;
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
textureResources.push({ sampler, view });
|
|
2017
|
-
}
|
|
2018
|
-
const entries: BindGroupEntry[] = [];
|
|
2019
|
-
let textureIndex = 0;
|
|
2020
|
-
for (let index = 0; index < derived.bglEntries.length; index += 1) {
|
|
2021
|
-
const expected = derived.bglEntries[index];
|
|
2022
|
-
if (expected?.buffer?.type === 'uniform' && buffer !== undefined) {
|
|
2023
|
-
entries.push({
|
|
2024
|
-
binding: expected.binding,
|
|
2025
|
-
resource: { kind: 'buffer', value: { buffer, size: payloadByteLength } },
|
|
2026
|
-
});
|
|
2027
|
-
continue;
|
|
2028
|
-
}
|
|
2029
|
-
const textureResource = textureResources[textureIndex];
|
|
2030
|
-
if (
|
|
2031
|
-
expected?.sampler?.type === 'filtering' &&
|
|
2032
|
-
derived.bglEntries[index + 1]?.texture !== undefined &&
|
|
2033
|
-
textureResource !== undefined
|
|
2034
|
-
) {
|
|
2035
|
-
entries.push({
|
|
2036
|
-
binding: expected.binding,
|
|
2037
|
-
resource: { kind: 'sampler', value: textureResource.sampler },
|
|
2038
|
-
});
|
|
2039
|
-
continue;
|
|
2040
|
-
}
|
|
2041
|
-
if (expected?.texture !== undefined && textureResource !== undefined) {
|
|
2042
|
-
entries.push({
|
|
2043
|
-
binding: expected.binding,
|
|
2044
|
-
resource: { kind: 'textureView', value: textureResource.view },
|
|
2045
|
-
});
|
|
2046
|
-
textureIndex += 1;
|
|
2047
|
-
continue;
|
|
2048
|
-
}
|
|
2049
|
-
if (buffer !== undefined) runtime.device.destroyBuffer(buffer);
|
|
2050
|
-
return err(new Error('prepared material schema contains unsupported binding kinds'));
|
|
2051
|
-
}
|
|
2052
|
-
const fallback = pipelineState.skylightFallback;
|
|
2053
|
-
if (fallback === null) {
|
|
2054
|
-
if (buffer !== undefined) runtime.device.destroyBuffer(buffer);
|
|
2055
|
-
return err(new Error('prepared material skylight fallback is unavailable'));
|
|
2056
|
-
}
|
|
2057
|
-
const completeEntries = assembleMaterialWithSkylightEntries(entries, {
|
|
2058
|
-
irradianceView: fallback.irradianceView,
|
|
2059
|
-
irradianceSampler: fallback.sampler,
|
|
2060
|
-
prefilterView: fallback.prefilterView,
|
|
2061
|
-
prefilterSampler: fallback.sampler,
|
|
2062
|
-
brdfLutView: fallback.brdfLutView,
|
|
2063
|
-
brdfLutSampler: fallback.sampler,
|
|
2064
|
-
intensityBuffer: fallback.intensityBuffer,
|
|
2065
|
-
});
|
|
2066
|
-
const group = runtime.device.createBindGroup({ layout, entries: completeEntries });
|
|
2067
|
-
if (!group.ok) {
|
|
2068
|
-
if (buffer !== undefined) runtime.device.destroyBuffer(buffer);
|
|
2069
|
-
return group;
|
|
2070
|
-
}
|
|
2071
|
-
if (buffer === undefined) return group;
|
|
2072
|
-
return ok({
|
|
2073
|
-
handle: group.value,
|
|
2074
|
-
dynamicOffsets: [0, 0],
|
|
2075
|
-
release: () => runtime.device.destroyBuffer(buffer),
|
|
2076
|
-
});
|
|
2077
|
-
};
|
|
2078
1840
|
const lastFrustumStats: { culled: number; total: number } = { culled: 0, total: 0 };
|
|
2079
1841
|
const lastVisibilityStats: { explicitlyHidden: number } = { explicitlyHidden: 0 };
|
|
1842
|
+
let lastMaterialTextureSources: MaterialTextureSourceInspection = {
|
|
1843
|
+
sourceFieldsVisited: 0,
|
|
1844
|
+
numericSharedRefProbes: 0,
|
|
1845
|
+
sourceCacheHits: 0,
|
|
1846
|
+
sourceCacheMisses: 0,
|
|
1847
|
+
producerRoutes: Object.freeze({}),
|
|
1848
|
+
};
|
|
2080
1849
|
let lastMeshMaterialBindings: readonly MeshMaterialBindingObservation[] = [];
|
|
2081
|
-
let
|
|
1850
|
+
let lastMeshMaterialBindingRenderables: readonly RenderableSnapshot[] | undefined;
|
|
2082
1851
|
const createPreparedResolverFactory =
|
|
2083
1852
|
(
|
|
2084
1853
|
runtime: RenderSystemInternals,
|
|
@@ -2115,7 +1884,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2115
1884
|
const pipeline = runtime.getPostProcessPipeline?.(
|
|
2116
1885
|
descriptor.shader,
|
|
2117
1886
|
fullscreen.bindGroupLayout,
|
|
2118
|
-
descriptor.colorFormats
|
|
1887
|
+
descriptor.colorFormats as readonly GPUTextureFormat[],
|
|
2119
1888
|
postProcessEntry,
|
|
2120
1889
|
);
|
|
2121
1890
|
if (pipeline !== null && pipeline !== undefined) {
|
|
@@ -2128,14 +1897,26 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2128
1897
|
? err(makePreparedPipelinePendingError())
|
|
2129
1898
|
: ok(pipeline);
|
|
2130
1899
|
}
|
|
2131
|
-
const
|
|
1900
|
+
const clusteredParticleMesh =
|
|
1901
|
+
runtime.device.caps.storageBuffer &&
|
|
1902
|
+
(descriptor.shader === 'forgeax::vfx-render.particles.mesh' ||
|
|
1903
|
+
descriptor.shader === 'forgeax::vfx-render.particles.mesh-inputs');
|
|
1904
|
+
const requestedVariantSet = clusteredParticleMesh
|
|
1905
|
+
? 'CLUSTER_FORWARD_AVAILABLE=true'
|
|
1906
|
+
: undefined;
|
|
1907
|
+
// A colorless prepared program is a depth-only pass. Vertex-only
|
|
1908
|
+
// shadow programs must use the depth policy; resolving them as
|
|
1909
|
+
// forward asks Dawn for a non-existent `fs_main` entry point.
|
|
1910
|
+
const preparedPassKind =
|
|
1911
|
+
descriptor.colorFormats.length === 0 ? 'shadow-caster' : 'forward';
|
|
1912
|
+
const preparedPipelineEntry = runtime.getMaterialShaderPipelineEntry?.(
|
|
2132
1913
|
descriptor.shader,
|
|
2133
1914
|
descriptor.colorFormats[0] === 'rgba16float',
|
|
2134
1915
|
descriptor.renderState,
|
|
2135
1916
|
descriptor.topology,
|
|
2136
1917
|
descriptor.indexFormat,
|
|
2137
|
-
|
|
2138
|
-
|
|
1918
|
+
requestedVariantSet,
|
|
1919
|
+
preparedPassKind,
|
|
2139
1920
|
undefined,
|
|
2140
1921
|
descriptor.sampleCount ?? 1,
|
|
2141
1922
|
// Prepared graphics own their declared attachment format. Passing
|
|
@@ -2150,7 +1931,41 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2150
1931
|
descriptor.vertexLayout,
|
|
2151
1932
|
undefined,
|
|
2152
1933
|
input.shaderModuleMode,
|
|
1934
|
+
undefined,
|
|
1935
|
+
undefined,
|
|
1936
|
+
undefined,
|
|
1937
|
+
undefined,
|
|
1938
|
+
undefined,
|
|
1939
|
+
descriptor.particleInputLanes,
|
|
2153
1940
|
);
|
|
1941
|
+
const preparedPipeline =
|
|
1942
|
+
preparedPipelineEntry === undefined
|
|
1943
|
+
? (runtime.getMaterialShaderPipeline?.(
|
|
1944
|
+
descriptor.shader,
|
|
1945
|
+
descriptor.colorFormats[0] === 'rgba16float',
|
|
1946
|
+
descriptor.renderState,
|
|
1947
|
+
descriptor.topology,
|
|
1948
|
+
descriptor.indexFormat,
|
|
1949
|
+
requestedVariantSet,
|
|
1950
|
+
preparedPassKind,
|
|
1951
|
+
undefined,
|
|
1952
|
+
descriptor.sampleCount ?? 1,
|
|
1953
|
+
descriptor.colorFormats[0] as GPUTextureFormat,
|
|
1954
|
+
undefined,
|
|
1955
|
+
descriptor.depthFormat === undefined
|
|
1956
|
+
? null
|
|
1957
|
+
: (descriptor.depthFormat as GPUTextureFormat),
|
|
1958
|
+
descriptor.vertexLayout,
|
|
1959
|
+
undefined,
|
|
1960
|
+
input.shaderModuleMode,
|
|
1961
|
+
undefined,
|
|
1962
|
+
undefined,
|
|
1963
|
+
undefined,
|
|
1964
|
+
undefined,
|
|
1965
|
+
undefined,
|
|
1966
|
+
descriptor.particleInputLanes,
|
|
1967
|
+
) ?? null)
|
|
1968
|
+
: (preparedPipelineEntry?.pipeline ?? null);
|
|
2154
1969
|
// A requested material shader is an exact pipeline contract. During
|
|
2155
1970
|
// async shader warmup, substituting the generic unlit pipeline can
|
|
2156
1971
|
// mismatch vertex layouts and HDR attachment formats, turning a
|
|
@@ -2167,7 +1982,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2167
1982
|
preparedRenderMaterialPipelines.add(pipeline as object);
|
|
2168
1983
|
}
|
|
2169
1984
|
}
|
|
2170
|
-
return pipeline === null
|
|
1985
|
+
return pipeline === null
|
|
1986
|
+
? err(makePreparedPipelinePendingError())
|
|
1987
|
+
: ok({
|
|
1988
|
+
handle: pipeline,
|
|
1989
|
+
standardLighting: preparedPipelineEntry?.group2Contract === 'cluster',
|
|
1990
|
+
});
|
|
2171
1991
|
},
|
|
2172
1992
|
resolveBindings: (descriptor, pipeline) => {
|
|
2173
1993
|
const materialShaderId = preparedMaterialPipelineShaders.get(pipeline as object);
|
|
@@ -2183,6 +2003,14 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2183
2003
|
if (bindingContract === 'view-and-scene-depth') {
|
|
2184
2004
|
return ok(undefined);
|
|
2185
2005
|
}
|
|
2006
|
+
if (
|
|
2007
|
+
preparedRenderMaterialPipelines.has(pipeline as object) &&
|
|
2008
|
+
descriptor.values.group === 0 &&
|
|
2009
|
+
descriptor.values.sceneDepth === undefined &&
|
|
2010
|
+
descriptor.values.sceneDepthBinding !== undefined
|
|
2011
|
+
) {
|
|
2012
|
+
return err(new Error('prepared scene-depth pipeline requires a scene target'));
|
|
2013
|
+
}
|
|
2186
2014
|
if (preparedGroup0Pipelines.has(pipeline as object)) {
|
|
2187
2015
|
const layout =
|
|
2188
2016
|
(materialShaderId === undefined
|
|
@@ -2236,6 +2064,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2236
2064
|
material.world,
|
|
2237
2065
|
material.guid,
|
|
2238
2066
|
layout,
|
|
2067
|
+
preparedFeatureSkylightResources,
|
|
2239
2068
|
);
|
|
2240
2069
|
}
|
|
2241
2070
|
return layout === undefined
|
|
@@ -2319,23 +2148,20 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2319
2148
|
createPreparedResolverCaches,
|
|
2320
2149
|
});
|
|
2321
2150
|
return {
|
|
2151
|
+
instances: instanceCollections,
|
|
2152
|
+
initializeSsr: ensureSsrFormatProbe,
|
|
2322
2153
|
get instanceCollectionsInspection(): readonly InstanceCollectionInspection[] {
|
|
2323
|
-
return instanceCollections._inspections(
|
|
2324
|
-
frameState.instanceResidency,
|
|
2325
|
-
frameState.frameNumber - 1,
|
|
2326
|
-
);
|
|
2154
|
+
return instanceCollections._inspections();
|
|
2327
2155
|
},
|
|
2328
2156
|
releaseProfilerCatalog(): void {
|
|
2329
2157
|
releaseProfilerCatalog?.();
|
|
2330
2158
|
releaseProfilerCatalog = undefined;
|
|
2331
2159
|
},
|
|
2332
2160
|
invalidateGeometryHistory(): void {
|
|
2333
|
-
frameState
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
frameState.successfulTemporalFrameIndex = 0;
|
|
2338
|
-
frameState.pendingTemporalCommit = { kind: 'none' };
|
|
2161
|
+
resetDynamicGeometryTemporalHistory(frameState);
|
|
2162
|
+
},
|
|
2163
|
+
bounds(world, entity) {
|
|
2164
|
+
return persistentRenderScene.bounds(world, entity);
|
|
2339
2165
|
},
|
|
2340
2166
|
get renderScene(): RenderSceneInspection {
|
|
2341
2167
|
return {
|
|
@@ -2350,32 +2176,46 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2350
2176
|
return reflectionProbeOwner.inspect();
|
|
2351
2177
|
},
|
|
2352
2178
|
get ssrDependencies(): SsrDependenciesInspection {
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
const
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
frameState.
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2179
|
+
return resolveSsrDependencies(frameState.ssrRequested === true);
|
|
2180
|
+
},
|
|
2181
|
+
get ssr(): SsrSpatialInspection {
|
|
2182
|
+
const camera = latestCamera;
|
|
2183
|
+
const lane = internals.standardProfile?.renderPath === 'deferred' ? 'deferred' : 'forward';
|
|
2184
|
+
const admission: SsrSpatialAdmission =
|
|
2185
|
+
frameState.ssrSpatialAdmission ??
|
|
2186
|
+
Object.freeze({
|
|
2187
|
+
status: camera?.screenSpaceReflection === undefined ? 'not-requested' : 'requested',
|
|
2188
|
+
lane,
|
|
2189
|
+
config: camera?.screenSpaceReflection,
|
|
2190
|
+
viewRange: camera === undefined ? 0 : camera.far - camera.near,
|
|
2191
|
+
work: zeroSsrAdmissionWork(),
|
|
2192
|
+
});
|
|
2193
|
+
const admitted = admission.status === 'admitted';
|
|
2194
|
+
const status =
|
|
2195
|
+
admitted && internals.ssrShaders === undefined
|
|
2196
|
+
? ('structural-only' as const)
|
|
2197
|
+
: admission.status;
|
|
2198
|
+
const graph = frameState.compiledFrameGraph?.inspect();
|
|
2199
|
+
const passRoster =
|
|
2200
|
+
admitted && graph !== undefined
|
|
2201
|
+
? graph.passes.filter((pass) => pass.name.startsWith('ssr-')).map((pass) => pass.name)
|
|
2202
|
+
: [];
|
|
2203
|
+
const history = frameState.ssrHistoryOwner?.inspect();
|
|
2204
|
+
const dependencies = resolveSsrDependencies(frameState.ssrRequested === true);
|
|
2205
|
+
const fallbackSource = dependencies.reflectionFallback?.source;
|
|
2206
|
+
return projectSsrSpatialInspection(admission, {
|
|
2207
|
+
status,
|
|
2208
|
+
...(history === undefined
|
|
2209
|
+
? {}
|
|
2210
|
+
: {
|
|
2211
|
+
history: {
|
|
2212
|
+
state: history.state,
|
|
2213
|
+
bytes: history.activeBytes + history.candidateBytes + history.retiringBytes,
|
|
2214
|
+
resetCount: history.resetCount,
|
|
2215
|
+
},
|
|
2216
|
+
}),
|
|
2217
|
+
passRoster,
|
|
2218
|
+
...(fallbackSource === undefined ? {} : { fallbackSource }),
|
|
2379
2219
|
});
|
|
2380
2220
|
},
|
|
2381
2221
|
get reflectionFallbackCompletion(): Promise<void> | undefined {
|
|
@@ -2387,6 +2227,27 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2387
2227
|
get environment(): EnvironmentInspection {
|
|
2388
2228
|
return environmentLifecycle.inspect();
|
|
2389
2229
|
},
|
|
2230
|
+
get autoExposure(): AutoExposureInspection | undefined {
|
|
2231
|
+
const camera = latestCamera;
|
|
2232
|
+
const state = frameState.autoExposureState;
|
|
2233
|
+
if (camera?.output?.exposure.kind !== 'auto' || state === undefined) return undefined;
|
|
2234
|
+
const actual = state.acceptedEv > 0 ? state.acceptedEv : null;
|
|
2235
|
+
return createAutoExposureInspection({
|
|
2236
|
+
requested: camera.output.exposure,
|
|
2237
|
+
actual,
|
|
2238
|
+
actualState:
|
|
2239
|
+
actual === null ? (state.receipt.committed ? 'gpu-resident' : 'fallback') : 'accepted',
|
|
2240
|
+
fallback: state.fallback,
|
|
2241
|
+
lastKnownGood: state.lastKnownGood,
|
|
2242
|
+
targetGeneration: state.targetGeneration,
|
|
2243
|
+
reset: state.reset,
|
|
2244
|
+
cost: { histogramBytes: AUTO_EXPOSURE_HISTOGRAM_BYTES, passCount: 3, physicalPassCount: 1 },
|
|
2245
|
+
receipt: state.receipt,
|
|
2246
|
+
});
|
|
2247
|
+
},
|
|
2248
|
+
get standardLut(): StandardLutInspection {
|
|
2249
|
+
return inspectStandardLutState(frameState.standardLutState);
|
|
2250
|
+
},
|
|
2390
2251
|
get temporal(): TemporalInspection {
|
|
2391
2252
|
return inspectTemporal(frameState.lastSuccessfulTemporalView, undefined, {
|
|
2392
2253
|
...(frameState.activeTemporalGpuState === undefined
|
|
@@ -2434,8 +2295,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2434
2295
|
if (producer === undefined || target === undefined) {
|
|
2435
2296
|
return undefined;
|
|
2436
2297
|
}
|
|
2437
|
-
const
|
|
2438
|
-
const
|
|
2298
|
+
const descriptor = target.descriptor.kind === 'texture' ? target.descriptor : undefined;
|
|
2299
|
+
const width = descriptor?.width ?? Math.max(1, internals.canvas.width);
|
|
2300
|
+
const height = descriptor?.height ?? Math.max(1, internals.canvas.height);
|
|
2439
2301
|
return Object.freeze({
|
|
2440
2302
|
identity: 'standard-scene-temporal',
|
|
2441
2303
|
producerId: 'forgeax::standard::scene-data',
|
|
@@ -2526,6 +2388,14 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2526
2388
|
return persistentRenderScene.pointsLinesSnapshots();
|
|
2527
2389
|
},
|
|
2528
2390
|
detachScene(world: World): void {
|
|
2391
|
+
const worldId = preparedWorlds.indexOf(world);
|
|
2392
|
+
const allocator = internals.getPipelineState()?.skinPaletteAllocator;
|
|
2393
|
+
if (allocator !== undefined && allocator !== null) {
|
|
2394
|
+
for (const slot of persistentRenderScene.compositionSlots()) {
|
|
2395
|
+
if (slot.worldId === worldId && slot.snapshot.skin !== undefined)
|
|
2396
|
+
allocator.releasePersistentSlice(slot.snapshot.skin.identity);
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2529
2399
|
persistentRenderScene.detach(world);
|
|
2530
2400
|
},
|
|
2531
2401
|
draw(
|
|
@@ -2543,8 +2413,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2543
2413
|
let submitted = false;
|
|
2544
2414
|
// A failed draw must never leave a previous frame eligible to publish a
|
|
2545
2415
|
// newly accepted dynamic-geometry candidate.
|
|
2546
|
-
|
|
2547
|
-
const frameConsumedDynamicGeometryBindings = new WeakMap<World, Map<number, number>>();
|
|
2416
|
+
dynamicGeometryFrames.begin();
|
|
2548
2417
|
if (profileSession !== undefined && opts.profileFrame === undefined) {
|
|
2549
2418
|
try {
|
|
2550
2419
|
ownsProfileFrame = profileSession.beginFrame(++directFrameId).ok;
|
|
@@ -2553,11 +2422,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2553
2422
|
}
|
|
2554
2423
|
}
|
|
2555
2424
|
try {
|
|
2425
|
+
internals.recoveryColdWorkGuard?.beginFrame();
|
|
2556
2426
|
pointsLinesOwner.beginFrame();
|
|
2557
2427
|
// cameraOwner drives the surfaced cameras + frustum
|
|
2558
2428
|
// cull; resourceOwner drives skylight/skybox/postProcess + per-world
|
|
2559
2429
|
// record config.
|
|
2560
|
-
const { cameraOwner, resourceOwner } = composition.owners;
|
|
2430
|
+
const { cameraOwner, resourceOwner, cameraEntityKey } = composition.owners;
|
|
2561
2431
|
// Keep the compiled graph as last-known-good until the candidate topology
|
|
2562
2432
|
// compiles. The failed candidate frame does not execute it; successful
|
|
2563
2433
|
// replacement retires it atomically in ensureCompiledFrameGraph.
|
|
@@ -2571,37 +2441,20 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2571
2441
|
}
|
|
2572
2442
|
dispatchCounts.unlit = 0;
|
|
2573
2443
|
|
|
2574
|
-
// feat-20260708-composited-multi-world-rendering M3 / D-2 / m3-i2:
|
|
2575
|
-
// extractFrames merges per-world snapshots (renderables + lights from
|
|
2576
|
-
// every world, cameras + singleton resources from the owner world),
|
|
2577
|
-
// runs read-only extractFrame per world over the already-updated World,
|
|
2578
|
-
// resets frame state once, and isolates
|
|
2579
|
-
// per-world errors (AC-09).
|
|
2580
|
-
// Single-world draw([world], { cameraOwner: 0, resourceOwner: 0 }) is the identity path
|
|
2581
|
-
// (worldId=0), byte-for-byte equivalent to the pre-M3 direct
|
|
2582
|
-
// extractFrame path (AC-03 regression guarantee).
|
|
2583
|
-
//
|
|
2584
|
-
// Entry validation (empty worlds / owner out of range) is enforced by
|
|
2585
|
-
// the public renderer.draw facade (createRenderer.ts, D-5) before this
|
|
2586
|
-
// internal method is reached; the owner world is guaranteed present.
|
|
2587
|
-
//
|
|
2588
|
-
// feat-20260709-editor-world-partition M1 / w5+w6 (D-3): per-world
|
|
2589
|
-
// record configuration (transparent-sort mode, fold buckets, skybox /
|
|
2590
|
-
// asset resolution) is read from the resource-owner world — the world
|
|
2591
|
-
// that owns skylight / skybox / postProcessParams. w6 sources it from
|
|
2592
|
-
// the dedicated resourceOwner index. The variable is named
|
|
2593
|
-
// `resourceWorld` so the record-stage reads are self-describing (they
|
|
2594
|
-
// are resource-owner reads, not camera reads).
|
|
2595
2444
|
const resourceWorld = compositionWorlds[resourceOwner] as World;
|
|
2596
2445
|
const frame = runProfiledRenderPhase(profileSession, 'extract', () => {
|
|
2597
2446
|
return persistentRenderScene.extractComposition(
|
|
2598
2447
|
compositionWorlds,
|
|
2599
2448
|
{ cameraOwner, resourceOwner },
|
|
2600
2449
|
internals.assets.catalogEpoch,
|
|
2601
|
-
(
|
|
2450
|
+
(renderables) =>
|
|
2602
2451
|
extractFrames(
|
|
2603
2452
|
compositionWorlds,
|
|
2604
|
-
{
|
|
2453
|
+
{
|
|
2454
|
+
cameraOwner,
|
|
2455
|
+
resourceOwner,
|
|
2456
|
+
...(cameraEntityKey === undefined ? {} : { cameraEntityKey }),
|
|
2457
|
+
},
|
|
2605
2458
|
internals.assets,
|
|
2606
2459
|
internals.getPipelineState(),
|
|
2607
2460
|
persistentRenderScene.materialSnapshotCacheStore(),
|
|
@@ -2626,13 +2479,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2626
2479
|
},
|
|
2627
2480
|
}),
|
|
2628
2481
|
cull: 'none',
|
|
2629
|
-
renderables: request === 'none' ? 'none' : 'full',
|
|
2630
|
-
...(request === 'none' || request === 'full'
|
|
2631
|
-
? {}
|
|
2632
|
-
: { renderableEntitiesByWorld: request.entitiesByWorld }),
|
|
2633
2482
|
retainHidden: true,
|
|
2483
|
+
renderables,
|
|
2634
2484
|
instanceCollections,
|
|
2635
|
-
...(internals.
|
|
2485
|
+
...(!internals.device.caps.storageBuffer ||
|
|
2486
|
+
internals.getMaterialShaderArtifact === undefined
|
|
2636
2487
|
? {}
|
|
2637
2488
|
: { getMaterialShaderArtifact: internals.getMaterialShaderArtifact }),
|
|
2638
2489
|
},
|
|
@@ -2641,7 +2492,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2641
2492
|
);
|
|
2642
2493
|
});
|
|
2643
2494
|
const {
|
|
2644
|
-
cameras,
|
|
2495
|
+
cameras: extractedCameras,
|
|
2645
2496
|
cubeCameras,
|
|
2646
2497
|
lights,
|
|
2647
2498
|
environment,
|
|
@@ -2649,6 +2500,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2649
2500
|
volumetricFog,
|
|
2650
2501
|
renderables,
|
|
2651
2502
|
dispatch,
|
|
2503
|
+
shadowCasterEntityKeys: extractedShadowCasterEntityKeys,
|
|
2504
|
+
shadowCasterDrawKeys: extractedShadowCasterDrawKeys,
|
|
2505
|
+
shadowCasterMembership: extractedShadowCasterMembership,
|
|
2652
2506
|
skylight,
|
|
2653
2507
|
skylightCount,
|
|
2654
2508
|
skybox,
|
|
@@ -2658,6 +2512,28 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2658
2512
|
visibilityStats,
|
|
2659
2513
|
postProcessParams,
|
|
2660
2514
|
} = frame;
|
|
2515
|
+
const cameras = extractedCameras;
|
|
2516
|
+
const preparedOutput = prepareStandardOutputResources(
|
|
2517
|
+
frameState,
|
|
2518
|
+
internals,
|
|
2519
|
+
cameras[0],
|
|
2520
|
+
compositionWorlds[cameraOwner] as World,
|
|
2521
|
+
);
|
|
2522
|
+
if (!preparedOutput.ok) {
|
|
2523
|
+
internals.errorRegistry.fire(preparedOutput.error);
|
|
2524
|
+
return false;
|
|
2525
|
+
}
|
|
2526
|
+
const stableShadowOwnership = rebaseShadowCasterOwnership(
|
|
2527
|
+
compositionWorlds,
|
|
2528
|
+
persistentRenderScene.visibilityWorldKeysFor(compositionWorlds),
|
|
2529
|
+
extractedShadowCasterEntityKeys,
|
|
2530
|
+
extractedShadowCasterDrawKeys,
|
|
2531
|
+
extractedShadowCasterMembership,
|
|
2532
|
+
);
|
|
2533
|
+
const shadowCasterEntityKeys = stableShadowOwnership.entityKeys;
|
|
2534
|
+
const shadowCasterDrawKeys = stableShadowOwnership.drawKeys;
|
|
2535
|
+
const shadowCasterMembership = stableShadowOwnership.membership;
|
|
2536
|
+
const shadowCasterProjection = persistentRenderScene.shadowCasterProjection();
|
|
2661
2537
|
lastDirectionalShadowLights = lights;
|
|
2662
2538
|
lastDirectionalShadowCandidate = 'failed';
|
|
2663
2539
|
lastDirectionalShadowError = lights.directionalShadowError;
|
|
@@ -2667,8 +2543,41 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2667
2543
|
cameras[0],
|
|
2668
2544
|
frameState.frameNumber,
|
|
2669
2545
|
skylight,
|
|
2546
|
+
frame.reflectionProbes?.some((probe) => probe.updateIntent === 'on-change')
|
|
2547
|
+
? JSON.stringify([
|
|
2548
|
+
persistentRenderScene.reflectionCaptureRevision(),
|
|
2549
|
+
lights.directional,
|
|
2550
|
+
lights.point,
|
|
2551
|
+
lights.spot,
|
|
2552
|
+
lights.rect,
|
|
2553
|
+
skylight,
|
|
2554
|
+
frame.skybox,
|
|
2555
|
+
environment?.environmentSignature,
|
|
2556
|
+
])
|
|
2557
|
+
: '',
|
|
2558
|
+
frame.skybox,
|
|
2670
2559
|
);
|
|
2671
2560
|
latestCamera = cameras[0];
|
|
2561
|
+
frameState.ssrRequested = latestCamera?.screenSpaceReflection !== undefined;
|
|
2562
|
+
// Resolve before a committed fallback change resets accumulation.
|
|
2563
|
+
// Fresh spatial SSR does not require a previous temporal submission.
|
|
2564
|
+
// Inspection uses the read-only projection above and never resets state.
|
|
2565
|
+
const ssrDependencies = resolveSsrDependencies(frameState.ssrRequested);
|
|
2566
|
+
const reset = resolveSsrAdmissionGeneration(
|
|
2567
|
+
ssrFallbackGeneration,
|
|
2568
|
+
ssrDependencies.reflectionFallback?.projectionGeneration,
|
|
2569
|
+
);
|
|
2570
|
+
if (reset.changed) {
|
|
2571
|
+
frameState.temporalFrameTransaction.reset('signature-change');
|
|
2572
|
+
frameState.temporalFrame = undefined;
|
|
2573
|
+
frameState.temporalFrameInput = undefined;
|
|
2574
|
+
frameState.lastSuccessfulTemporalView = undefined;
|
|
2575
|
+
frameState.successfulTemporalFrameIndex = 0;
|
|
2576
|
+
frameState.pendingTemporalCommit = { kind: 'none' };
|
|
2577
|
+
frameState.ssrHistoryOwner?.reset('reflection-generation');
|
|
2578
|
+
frameState.ssrHistoryCandidate = undefined;
|
|
2579
|
+
}
|
|
2580
|
+
ssrFallbackGeneration = reset.generation;
|
|
2672
2581
|
persistentRenderScene.updateVisibilityFacet(compositionWorlds, latestCamera, renderables);
|
|
2673
2582
|
let occlusionProjection:
|
|
2674
2583
|
| import('./scene/visibility/occlusion-runtime').OcclusionFrameProjection
|
|
@@ -2940,6 +2849,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2940
2849
|
if (temporalDemanded) {
|
|
2941
2850
|
persistentRenderScene.prepareTemporalFrame(submissionRenderables);
|
|
2942
2851
|
}
|
|
2852
|
+
frameState.environmentFrame = environment as
|
|
2853
|
+
| import('./environment/frame').SelectedEnvironmentFrame
|
|
2854
|
+
| undefined;
|
|
2943
2855
|
environmentLifecycle.bindScope(internals.deviceScope);
|
|
2944
2856
|
if (fogFailure !== undefined) {
|
|
2945
2857
|
environmentLifecycle.recordSelectionFailure(fogFailure);
|
|
@@ -2970,8 +2882,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2970
2882
|
updateTransmissionInspection(transmissionAntialias, false);
|
|
2971
2883
|
return false;
|
|
2972
2884
|
}
|
|
2973
|
-
if (
|
|
2974
|
-
|
|
2885
|
+
if (lastMeshMaterialBindingRenderables !== renderables) {
|
|
2886
|
+
lastMeshMaterialBindingRenderables = renderables;
|
|
2975
2887
|
lastMeshMaterialBindings = renderables.map((renderable) => {
|
|
2976
2888
|
const materialWorld = preparedWorlds[renderable.worldId];
|
|
2977
2889
|
return projectMeshMaterialBindingObservation({
|
|
@@ -3024,6 +2936,15 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3024
2936
|
lastFrustumStats.culled = frustumStats.culled;
|
|
3025
2937
|
lastFrustumStats.total = frustumStats.total;
|
|
3026
2938
|
lastVisibilityStats.explicitlyHidden = visibilityStats.explicitlyHidden;
|
|
2939
|
+
if (frame.materialTextureSources !== undefined) {
|
|
2940
|
+
lastMaterialTextureSources = Object.freeze({
|
|
2941
|
+
sourceFieldsVisited: frame.materialTextureSources.sourceFieldsVisited,
|
|
2942
|
+
numericSharedRefProbes: frame.materialTextureSources.numericSharedRefProbes,
|
|
2943
|
+
sourceCacheHits: frame.materialTextureSources.sourceCacheHits,
|
|
2944
|
+
sourceCacheMisses: frame.materialTextureSources.sourceCacheMisses,
|
|
2945
|
+
producerRoutes: Object.freeze({ ...frame.materialTextureSources.producerRoutes }),
|
|
2946
|
+
});
|
|
2947
|
+
}
|
|
3027
2948
|
const featureTargets =
|
|
3028
2949
|
preparedPipelineState === null || cameras[0] === undefined
|
|
3029
2950
|
? []
|
|
@@ -3034,6 +2955,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3034
2955
|
storageBuffer: internals.device.caps.storageBuffer,
|
|
3035
2956
|
multisample: internals.device.caps.backendKind !== 'wgpu-webgl2',
|
|
3036
2957
|
});
|
|
2958
|
+
preparedFeatureSkylightResources =
|
|
2959
|
+
preparedPipelineState === null
|
|
2960
|
+
? undefined
|
|
2961
|
+
: resolveMaterialSkylight(internals, preparedPipelineState, skylight, skylightCount)
|
|
2962
|
+
.skylightResources;
|
|
3037
2963
|
let featureGraphCandidate: RenderFeatureGraphCandidate | undefined;
|
|
3038
2964
|
const preparedResourceBatches = runProfiledRenderPhase(profileSession, 'features', () => {
|
|
3039
2965
|
if (internals.featureHost === undefined) return [];
|
|
@@ -3049,6 +2975,28 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3049
2975
|
...(internals.getMaterialShaderBindingContract === undefined
|
|
3050
2976
|
? {}
|
|
3051
2977
|
: { materialShaderBindingContract: internals.getMaterialShaderBindingContract }),
|
|
2978
|
+
...(preparedPipelineState === null
|
|
2979
|
+
? {}
|
|
2980
|
+
: {
|
|
2981
|
+
preparedDataInterfaces: {
|
|
2982
|
+
camera: {
|
|
2983
|
+
kind: 'buffer' as const,
|
|
2984
|
+
value: preparedPipelineState.viewUniformBuffer,
|
|
2985
|
+
size: 64,
|
|
2986
|
+
usage: 'uniform' as const,
|
|
2987
|
+
},
|
|
2988
|
+
'scene-depth': {
|
|
2989
|
+
kind: 'texture-view' as const,
|
|
2990
|
+
value: preparedPipelineState.shadowFallbackTextureView,
|
|
2991
|
+
},
|
|
2992
|
+
get noise() {
|
|
2993
|
+
const value = resolveFeatureNoise(frameState.frameNumber);
|
|
2994
|
+
return value === undefined
|
|
2995
|
+
? undefined
|
|
2996
|
+
: { kind: 'texture-view' as const, value };
|
|
2997
|
+
},
|
|
2998
|
+
},
|
|
2999
|
+
}),
|
|
3052
3000
|
createPreparedGraphicsResolver: preparedResolverFactory,
|
|
3053
3001
|
gpuWork: featureGpuWork,
|
|
3054
3002
|
});
|
|
@@ -3072,10 +3020,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3072
3020
|
featureGraphCandidate = {
|
|
3073
3021
|
plans: featureFrame.plans,
|
|
3074
3022
|
fullscreenEffects: featureFrame.fullscreenEffects,
|
|
3075
|
-
...(featureFrame.
|
|
3076
|
-
? {}
|
|
3077
|
-
: {
|
|
3023
|
+
...(featureFrame.requiresPreparedResourceKey
|
|
3024
|
+
? { preparedResourceKey: `frame-${frameState.frameNumber}` }
|
|
3025
|
+
: {}),
|
|
3078
3026
|
onRejected: () => {
|
|
3027
|
+
featureFrame.onAborted();
|
|
3079
3028
|
for (const batch of featureFrame.preparedResourceBatches) {
|
|
3080
3029
|
const released = batch.release();
|
|
3081
3030
|
if (!released.ok) {
|
|
@@ -3085,8 +3034,15 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3085
3034
|
discardPostProcessParamsCandidate(postProcessParamsCandidate.value);
|
|
3086
3035
|
},
|
|
3087
3036
|
onAbandoned: () => {
|
|
3037
|
+
featureFrame.onAborted();
|
|
3088
3038
|
discardPostProcessParamsCandidate(postProcessParamsCandidate.value);
|
|
3089
3039
|
},
|
|
3040
|
+
onSubmitted: () => {
|
|
3041
|
+
featureFrame.onSubmitted();
|
|
3042
|
+
},
|
|
3043
|
+
onAborted: () => {
|
|
3044
|
+
featureFrame.onAborted();
|
|
3045
|
+
},
|
|
3090
3046
|
onAccepted: () => {
|
|
3091
3047
|
for (const [id, previous] of activeFeaturePostProcessEntries) {
|
|
3092
3048
|
const next = featureFrame.fullscreenEffects.get(id);
|
|
@@ -3107,6 +3063,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3107
3063
|
activeFeaturePostProcessEntries = featureFrame.fullscreenEffects;
|
|
3108
3064
|
},
|
|
3109
3065
|
};
|
|
3066
|
+
recordRenderFeatureCandidate(internals, featureGraphCandidate);
|
|
3110
3067
|
return featureFrame.preparedResourceBatches;
|
|
3111
3068
|
});
|
|
3112
3069
|
|
|
@@ -3184,14 +3141,38 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3184
3141
|
if (cameras[0]?.bloom === 'on') {
|
|
3185
3142
|
internals.getPipelineState()?.perPassResources.ensureBloomResources?.();
|
|
3186
3143
|
}
|
|
3144
|
+
const liveOutput = cameras[0]?.output;
|
|
3145
|
+
const hasLiveFeatureState =
|
|
3146
|
+
liveOutput !== undefined ||
|
|
3147
|
+
frameState.autoExposureGpuResources !== undefined ||
|
|
3148
|
+
frameState.pendingAutoExposureGpuResources !== undefined ||
|
|
3149
|
+
frameState.autoExposureState !== undefined ||
|
|
3150
|
+
frameState.pendingAutoExposureState !== undefined ||
|
|
3151
|
+
frameState.standardLutGpuResources !== undefined ||
|
|
3152
|
+
frameState.pendingStandardLutGpuResources !== undefined ||
|
|
3153
|
+
frameState.standardLutState.resident !== null ||
|
|
3154
|
+
frameState.pendingStandardLutState !== undefined;
|
|
3155
|
+
if (hasLiveFeatureState) {
|
|
3156
|
+
const cameraWorld = compositionWorlds[cameraOwner] as World;
|
|
3157
|
+
const deltaTime = cameraWorld.getResource(Time).delta;
|
|
3158
|
+
stageLiveFeatureState(
|
|
3159
|
+
cameras[0],
|
|
3160
|
+
Number.isFinite(deltaTime) ? Math.max(0, deltaTime) : 0,
|
|
3161
|
+
);
|
|
3162
|
+
}
|
|
3163
|
+
const probeCaptureScene =
|
|
3164
|
+
shadowCasterProjection !== undefined &&
|
|
3165
|
+
reflectionProbeRecord.graph.work.some((work) => work.rawCaptureFace !== undefined)
|
|
3166
|
+
? projectCaptureScene(shadowCasterProjection, submissionRenderables, orderedDispatch)
|
|
3167
|
+
: undefined;
|
|
3187
3168
|
submitted = runProfiledRenderPhase(profileSession, 'record', () =>
|
|
3188
3169
|
recordFrame(
|
|
3189
3170
|
internals,
|
|
3190
3171
|
resourceWorld,
|
|
3191
3172
|
cameras,
|
|
3192
3173
|
lights,
|
|
3193
|
-
|
|
3194
|
-
orderedDispatch,
|
|
3174
|
+
probeCaptureScene?.renderables ?? submissionRenderables,
|
|
3175
|
+
probeCaptureScene?.displayDispatch ?? orderedDispatch,
|
|
3195
3176
|
frameState,
|
|
3196
3177
|
dispatchCounts,
|
|
3197
3178
|
bindGroupCounts,
|
|
@@ -3221,37 +3202,28 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3221
3202
|
scheduler: cubeCaptureScheduler,
|
|
3222
3203
|
state: cubeCaptureState,
|
|
3223
3204
|
reflectionProbes: reflectionProbeRecord,
|
|
3205
|
+
...(probeCaptureScene === undefined
|
|
3206
|
+
? {}
|
|
3207
|
+
: { captureDispatch: probeCaptureScene.captureDispatch }),
|
|
3224
3208
|
} satisfies CubeCaptureFrameInput,
|
|
3225
3209
|
environment?.environmentSignature ?? '',
|
|
3226
3210
|
environment?.fogSignature ?? '',
|
|
3227
3211
|
environmentReady && environment !== undefined,
|
|
3228
3212
|
persistentRenderScene.transmissionTopologyDemand(),
|
|
3213
|
+
shadowCasterEntityKeys,
|
|
3214
|
+
shadowCasterDrawKeys,
|
|
3229
3215
|
volumetricFog,
|
|
3230
3216
|
timingCapture,
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
bindings = new Map();
|
|
3238
|
-
frameConsumedDynamicGeometryBindings.set(world, bindings);
|
|
3239
|
-
}
|
|
3240
|
-
bindings.set(renderable.entityKey, renderable.assetHandle);
|
|
3241
|
-
},
|
|
3217
|
+
shadowCasterMembership,
|
|
3218
|
+
shadowCasterProjection,
|
|
3219
|
+
worldKeys,
|
|
3220
|
+
undefined,
|
|
3221
|
+
ssrDependencies,
|
|
3222
|
+
dynamicGeometryFrames.onRenderableDraw(compositionWorlds),
|
|
3242
3223
|
),
|
|
3243
3224
|
);
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
}
|
|
3247
|
-
if (submitted) {
|
|
3248
|
-
try {
|
|
3249
|
-
internals.recoveryColdWorkGuard?.finish();
|
|
3250
|
-
} catch (cause) {
|
|
3251
|
-
submitted = false;
|
|
3252
|
-
throw cause;
|
|
3253
|
-
}
|
|
3254
|
-
}
|
|
3225
|
+
dynamicGeometryFrames.commit(submitted);
|
|
3226
|
+
if (!submitted) discardLiveFeatureState();
|
|
3255
3227
|
if (submitted && lastLodOcclusionInspection !== undefined) {
|
|
3256
3228
|
const query = ensureOcclusionRuntime().inspect();
|
|
3257
3229
|
lastLodOcclusionInspection = {
|
|
@@ -3346,6 +3318,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3346
3318
|
}
|
|
3347
3319
|
}
|
|
3348
3320
|
} catch (err) {
|
|
3321
|
+
discardLiveFeatureState();
|
|
3349
3322
|
if (!submitted) {
|
|
3350
3323
|
internals.getPipelineState()?.perPassResources.discardBloomResources?.();
|
|
3351
3324
|
}
|
|
@@ -3359,7 +3332,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3359
3332
|
}
|
|
3360
3333
|
: err instanceof RhiError
|
|
3361
3334
|
? err
|
|
3362
|
-
: {
|
|
3335
|
+
: {
|
|
3336
|
+
code: 'unknown' as const,
|
|
3337
|
+
message: String(err),
|
|
3338
|
+
name: (err as Error)?.name,
|
|
3339
|
+
};
|
|
3363
3340
|
internals.errorRegistry.fire(
|
|
3364
3341
|
new RhiError({
|
|
3365
3342
|
code: 'webgpu-runtime-error',
|
|
@@ -3369,6 +3346,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3369
3346
|
}),
|
|
3370
3347
|
);
|
|
3371
3348
|
} finally {
|
|
3349
|
+
internals.recoveryColdWorkGuard?.endFrame();
|
|
3372
3350
|
if (ownsProfileFrame) {
|
|
3373
3351
|
try {
|
|
3374
3352
|
profileSession?.endFrame();
|
|
@@ -3379,14 +3357,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3379
3357
|
}
|
|
3380
3358
|
return submitted;
|
|
3381
3359
|
},
|
|
3382
|
-
isDynamicGeometryConsumed(
|
|
3383
|
-
world
|
|
3384
|
-
entity: number,
|
|
3385
|
-
meshHandle: number | undefined,
|
|
3386
|
-
): boolean {
|
|
3387
|
-
if (!Number.isInteger(entity) || meshHandle === undefined) return false;
|
|
3388
|
-
return lastSubmittedDynamicGeometryBindings.get(world)?.get(entity) === meshHandle;
|
|
3389
|
-
},
|
|
3360
|
+
isDynamicGeometryConsumed: (world, entity, meshHandle) =>
|
|
3361
|
+
dynamicGeometryFrames.isConsumed(world, entity, meshHandle),
|
|
3390
3362
|
pipelineDispatchCounts: dispatchCounts,
|
|
3391
3363
|
observeCurrentFrame(options: FrameObservationOptions) {
|
|
3392
3364
|
const currentFrameId = frameState.frameNumber - 1;
|
|
@@ -3457,6 +3429,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3457
3429
|
get perFrameGraphInfo(): CompiledRenderGraphInfo | undefined {
|
|
3458
3430
|
return frameState.compiledFrameGraph?.inspect();
|
|
3459
3431
|
},
|
|
3432
|
+
get featureGraphInspection(): import('./inspection-types').RenderFeatureGraphInspection {
|
|
3433
|
+
return getRenderFeatureGraphInspection(internals);
|
|
3434
|
+
},
|
|
3435
|
+
get materialTextureSources(): MaterialTextureSourceInspection {
|
|
3436
|
+
return lastMaterialTextureSources;
|
|
3437
|
+
},
|
|
3460
3438
|
get recoveryEvidence(): RecoveryProductionEvidence {
|
|
3461
3439
|
const graph = frameState.compiledFrameGraph?.inspect();
|
|
3462
3440
|
return Object.freeze({
|
|
@@ -3486,7 +3464,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3486
3464
|
? config
|
|
3487
3465
|
: {
|
|
3488
3466
|
clusterGrid: DEFAULT_CLUSTER_GRID,
|
|
3489
|
-
|
|
3467
|
+
ssao: {
|
|
3468
|
+
enabled: profileConfig.ssao !== false,
|
|
3469
|
+
...(typeof profileConfig.ssao === 'object' ? profileConfig.ssao : {}),
|
|
3470
|
+
},
|
|
3490
3471
|
...config,
|
|
3491
3472
|
};
|
|
3492
3473
|
if (resolvedConfig?.clusterGrid !== undefined) {
|
|
@@ -3583,6 +3564,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3583
3564
|
(internals as TimingSessionHost).gpuPassTimingSubmittedWork = undefined;
|
|
3584
3565
|
(internals as TimingSessionHost).gpuPassTimingFrameIdentity = undefined;
|
|
3585
3566
|
(internals as TimingSessionHost).gpuPassTimingBeginReason = undefined;
|
|
3567
|
+
internals.getPipelineState()?.skinPaletteAllocator?.dispose();
|
|
3586
3568
|
pointsLinesOwner.dispose();
|
|
3587
3569
|
persistentRenderScene.dispose();
|
|
3588
3570
|
instanceCollections.dispose();
|
|
@@ -3590,6 +3572,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3590
3572
|
occlusionRuntime?.dispose();
|
|
3591
3573
|
disposeFeatureGpuWork();
|
|
3592
3574
|
reflectionProbeOwner.dispose();
|
|
3575
|
+
frameState.ssrHistoryOwner?.dispose();
|
|
3576
|
+
frameState.ssrHistoryOwner = undefined;
|
|
3577
|
+
frameState.ssrHistoryCandidate = undefined;
|
|
3578
|
+
frameState.ssrSpatialAdmission = undefined;
|
|
3593
3579
|
// Bloom generations are renderer-owned rather than graph-owned. Drain
|
|
3594
3580
|
// candidate, active, and fence-retiring bundles before the rest of the
|
|
3595
3581
|
// frame state is torn down; the owner callback is idempotent so the
|
|
@@ -3610,6 +3596,19 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3610
3596
|
frameState.lastSuccessfulCameraAntialias = undefined;
|
|
3611
3597
|
frameState.currentDirectionalShadowView = null;
|
|
3612
3598
|
frameState.currentSpotShadowView = null;
|
|
3599
|
+
if (frameState.pendingAutoExposureGpuResources !== undefined) {
|
|
3600
|
+
retireAutoExposureGpuResources(frameState.pendingAutoExposureGpuResources);
|
|
3601
|
+
frameState.pendingAutoExposureGpuResources = undefined;
|
|
3602
|
+
}
|
|
3603
|
+
if (frameState.autoExposureGpuResources !== undefined) {
|
|
3604
|
+
retireAutoExposureGpuResources(frameState.autoExposureGpuResources);
|
|
3605
|
+
frameState.autoExposureGpuResources = undefined;
|
|
3606
|
+
}
|
|
3607
|
+
frameState.autoExposureState = undefined;
|
|
3608
|
+
frameState.pendingAutoExposureState = undefined;
|
|
3609
|
+
frameState.pendingStandardLutGpuResources = undefined;
|
|
3610
|
+
frameState.standardLutGpuResources = undefined;
|
|
3611
|
+
frameState.pendingStandardLutState = undefined;
|
|
3613
3612
|
if (frameState.temporalGpuState !== undefined) {
|
|
3614
3613
|
retireTemporalGpuState(frameState.temporalGpuState);
|
|
3615
3614
|
frameState.temporalGpuState = undefined;
|
|
@@ -3655,7 +3654,6 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3655
3654
|
// so destroy failures fire structured errors (unified per-frame +
|
|
3656
3655
|
// dispose error strategy).
|
|
3657
3656
|
disposeInstanceBuffers(frameState.instanceBuffers, internals.errorRegistry);
|
|
3658
|
-
frameState.instanceResidency?.clear();
|
|
3659
3657
|
if (frameState.instanceBufferChunks !== undefined) {
|
|
3660
3658
|
disposeInstanceBufferChunks(frameState.instanceBufferChunks, internals.errorRegistry);
|
|
3661
3659
|
}
|
|
@@ -3696,9 +3694,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3696
3694
|
// their handles without invoking destroy on a device that can no longer
|
|
3697
3695
|
// service cleanup; the staged candidate owns the replacement buffers.
|
|
3698
3696
|
pointsLinesOwner.abandonForDeviceLoss();
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
ssrFormatProbe = undefined;
|
|
3697
|
+
resetStandardOutputForDeviceLoss(frameState, internals.deviceScope.generation);
|
|
3698
|
+
ssrFormatReceipts.delete(internals.device);
|
|
3702
3699
|
ssrFallbackGeneration = undefined;
|
|
3703
3700
|
transmissionAdmission.markDeviceLost();
|
|
3704
3701
|
lastTransmissionKey = '';
|
|
@@ -3716,13 +3713,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3716
3713
|
updateTransmissionInspection(lastTransmissionAntialias, false);
|
|
3717
3714
|
persistentRenderScene.resetGpuForRecover();
|
|
3718
3715
|
gpuDrivenProduction.dispose();
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
// explicitly so the first published draw never routes through an owner
|
|
3722
|
-
// recreated against the old physical device.
|
|
3723
|
-
gpuDrivenProduction = GpuDrivenProduction.forDevice(
|
|
3716
|
+
gpuDrivenRecoveryCount += 1;
|
|
3717
|
+
gpuDrivenProduction = createGpuDrivenOwner(
|
|
3724
3718
|
replacementDevice ?? internals.device,
|
|
3725
3719
|
gpuDrivenShaderFactory,
|
|
3720
|
+
gpuDrivenRecoveryCount,
|
|
3726
3721
|
);
|
|
3727
3722
|
occlusionRuntime?.dispose();
|
|
3728
3723
|
// The replacement device is installed by the host after this hook. Do
|
|
@@ -3732,6 +3727,13 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3732
3727
|
disposeFeatureGpuWork();
|
|
3733
3728
|
featureGpuWork = createFeatureGpuWorkOwner(internals);
|
|
3734
3729
|
reflectionProbeOwner.dispose();
|
|
3730
|
+
frameState.ssrHistoryOwner?.dispose();
|
|
3731
|
+
frameState.ssrHistoryOwner = undefined;
|
|
3732
|
+
frameState.ssrHistoryCandidate = undefined;
|
|
3733
|
+
frameState.ssrSpatialAdmission = undefined;
|
|
3734
|
+
frameState.ssrRequested = false;
|
|
3735
|
+
frameState.ssrLastCameraEntity = undefined;
|
|
3736
|
+
frameState.ssrLastHistoryVersion = undefined;
|
|
3735
3737
|
// A recovered device cannot retain handles from the lost device. The
|
|
3736
3738
|
// Bloom owner abandons candidates and retires every committed generation
|
|
3737
3739
|
// before the new PipelineState is rebuilt.
|
|
@@ -3801,7 +3803,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3801
3803
|
frameState.retiredCompiledFrameGraphs.clear();
|
|
3802
3804
|
frameState.instanceBuffers.clear();
|
|
3803
3805
|
frameState.instanceBufferChunks?.clear();
|
|
3804
|
-
|
|
3806
|
+
instanceCollections._resetResidency();
|
|
3805
3807
|
delete frameState.probeBlendRecordBuffer;
|
|
3806
3808
|
frameState.probeBlendRecordBufferCapacity = 0;
|
|
3807
3809
|
frameState.probeBlendBuffers.clear();
|
|
@@ -3818,7 +3820,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3818
3820
|
frameState.instancesBgPerEntity.clear();
|
|
3819
3821
|
frameState.materialBgShared.clear();
|
|
3820
3822
|
frameState.materialBgAssemblyCache.clear();
|
|
3821
|
-
frameState.
|
|
3823
|
+
frameState.shadowMaterialBindGroups = new WeakMap();
|
|
3822
3824
|
frameState.postProcessBgCache = new WeakMap();
|
|
3823
3825
|
// Fullscreen PSOs are cached outside frameState because the normal
|
|
3824
3826
|
// path reuses them across frames. They still carry opaque handles from
|
|
@@ -3844,124 +3846,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3844
3846
|
publishRecoveryPostProcessResources(prepared.value);
|
|
3845
3847
|
},
|
|
3846
3848
|
prepareRecoveryRoots(runtime: RecoveryRootRuntime): RecoveryRootBundle {
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
const candidateEnvironmentLifecycle = environmentLifecycle.createRecoveryCandidate(
|
|
3851
|
-
runtime.scope,
|
|
3852
|
-
);
|
|
3853
|
-
const roots: LifecycleResourceSpec<unknown>[] = [];
|
|
3854
|
-
let candidateEnvironmentGeneration: EnvironmentGeneration | undefined;
|
|
3855
|
-
let environmentRootCleaned = false;
|
|
3856
|
-
let published = false;
|
|
3857
|
-
if (candidateEnvironmentLifecycle.hasRecoveryFrame()) {
|
|
3858
|
-
const environmentRoot = candidateEnvironmentLifecycle.createRecoveryRoot(runtime.scope);
|
|
3859
|
-
roots.push({
|
|
3860
|
-
...environmentRoot,
|
|
3861
|
-
create: async () => {
|
|
3862
|
-
const generation = (await environmentRoot.create()) as EnvironmentGeneration;
|
|
3863
|
-
candidateEnvironmentGeneration = generation;
|
|
3864
|
-
return generation;
|
|
3865
|
-
},
|
|
3866
|
-
cleanup: (value) => {
|
|
3867
|
-
if (environmentRootCleaned) return;
|
|
3868
|
-
environmentRootCleaned = true;
|
|
3869
|
-
if (candidateEnvironmentGeneration === value) {
|
|
3870
|
-
candidateEnvironmentGeneration = undefined;
|
|
3871
|
-
}
|
|
3872
|
-
if (published) {
|
|
3873
|
-
candidateEnvironmentLifecycle.retirePublishedGeneration(
|
|
3874
|
-
value as EnvironmentGeneration,
|
|
3875
|
-
);
|
|
3876
|
-
} else {
|
|
3877
|
-
environmentRoot.cleanup(value);
|
|
3878
|
-
}
|
|
3879
|
-
},
|
|
3880
|
-
});
|
|
3881
|
-
}
|
|
3882
|
-
const graphCandidate = runtime.graphCandidate;
|
|
3883
|
-
if (graphCandidate !== undefined) {
|
|
3884
|
-
const releaseGraphCandidate = (): void => graphCandidate.release();
|
|
3885
|
-
const compiledGraph = graphCandidate.frameState.compiledFrameGraph;
|
|
3886
|
-
if (compiledGraph !== null) {
|
|
3887
|
-
roots.push({
|
|
3888
|
-
kind: 'pipeline',
|
|
3889
|
-
create: () => {
|
|
3890
|
-
if (!runtime.scope.isAlive()) {
|
|
3891
|
-
throw new Error('Recovery graph candidate scope is not active.');
|
|
3892
|
-
}
|
|
3893
|
-
if (graphCandidate.frameState.compiledFrameGraph !== compiledGraph) {
|
|
3894
|
-
throw new Error('Recovery graph candidate was changed before aggregate assembly.');
|
|
3895
|
-
}
|
|
3896
|
-
return compiledGraph;
|
|
3897
|
-
},
|
|
3898
|
-
// All graph/feature/GPU-driven candidate resources share one
|
|
3899
|
-
// owner. The root is a real release seam, not a marker; the
|
|
3900
|
-
// candidate latch makes every root cleanup call harmless after
|
|
3901
|
-
// the first one.
|
|
3902
|
-
cleanup: releaseGraphCandidate,
|
|
3903
|
-
});
|
|
3904
|
-
}
|
|
3905
|
-
if (graphCandidate.featureHost !== undefined) {
|
|
3906
|
-
const featureRoot = graphCandidate.featureHost.createRecoveryRoot(runtime.scope);
|
|
3907
|
-
roots.push({ ...featureRoot, cleanup: releaseGraphCandidate });
|
|
3908
|
-
}
|
|
3909
|
-
if (graphCandidate.featureGpuWork !== undefined) {
|
|
3910
|
-
const featureWorkRoot = graphCandidate.featureGpuWork.createRecoveryRoot(runtime.scope);
|
|
3911
|
-
roots.push({ ...featureWorkRoot, cleanup: releaseGraphCandidate });
|
|
3912
|
-
}
|
|
3913
|
-
if (graphCandidate.gpuDrivenProduction !== undefined) {
|
|
3914
|
-
const productionRoot = graphCandidate.gpuDrivenProduction.createRecoveryRoot(
|
|
3915
|
-
runtime.scope,
|
|
3916
|
-
);
|
|
3917
|
-
roots.push({ ...productionRoot, cleanup: releaseGraphCandidate });
|
|
3918
|
-
}
|
|
3919
|
-
if (graphCandidate.gpuDrivenScene?.state !== undefined) {
|
|
3920
|
-
const sceneRoot = graphCandidate.gpuDrivenScene.createRecoveryRoot(runtime.scope);
|
|
3921
|
-
roots.push({ ...sceneRoot, cleanup: releaseGraphCandidate });
|
|
3922
|
-
}
|
|
3923
|
-
if (graphCandidate.pointsLines !== undefined) {
|
|
3924
|
-
const pointsLinesRoot = graphCandidate.pointsLines.createRecoveryRoot(runtime.scope);
|
|
3925
|
-
roots.push({ ...pointsLinesRoot, cleanup: releaseGraphCandidate });
|
|
3926
|
-
}
|
|
3927
|
-
if (runtime.gpuStore.recoveryResourceCount() > 0) {
|
|
3928
|
-
const gpuStoreRoot = runtime.gpuStore.createRecoveryRoot(runtime.scope);
|
|
3929
|
-
roots.push({ ...gpuStoreRoot, cleanup: releaseGraphCandidate });
|
|
3930
|
-
}
|
|
3931
|
-
}
|
|
3932
|
-
let discarded = false;
|
|
3933
|
-
return {
|
|
3934
|
-
roots: Object.freeze(roots),
|
|
3935
|
-
publish: () => {
|
|
3936
|
-
if (published || discarded) return;
|
|
3937
|
-
if (
|
|
3938
|
-
candidateEnvironmentGeneration !== undefined &&
|
|
3939
|
-
!candidateEnvironmentGeneration.retired
|
|
3940
|
-
) {
|
|
3941
|
-
environmentLifecycle.retireActiveForReplacement();
|
|
3942
|
-
candidateEnvironmentLifecycle.publish(candidateEnvironmentGeneration);
|
|
3943
|
-
}
|
|
3944
|
-
published = true;
|
|
3945
|
-
environmentLifecycle = candidateEnvironmentLifecycle;
|
|
3946
|
-
Object.assign(frameState, { environmentLifecycle });
|
|
3947
|
-
},
|
|
3948
|
-
discard: () => {
|
|
3949
|
-
if (published || discarded) return;
|
|
3950
|
-
discarded = true;
|
|
3951
|
-
if (candidateEnvironmentGeneration !== undefined) {
|
|
3952
|
-
candidateEnvironmentLifecycle.discard(candidateEnvironmentGeneration);
|
|
3953
|
-
candidateEnvironmentGeneration = undefined;
|
|
3954
|
-
}
|
|
3955
|
-
candidateEnvironmentLifecycle.discardRecoveryCandidates();
|
|
3956
|
-
// The transaction can fail before it reaches any graph root (for
|
|
3957
|
-
// example while the environment root is created). Keep the graph,
|
|
3958
|
-
// feature, GPU-driven, and residency resources on the same real
|
|
3959
|
-
// candidate owner in that case; later scope/factory cleanup is a
|
|
3960
|
-
// harmless repeat through the candidate latch.
|
|
3961
|
-
graphCandidate?.release();
|
|
3962
|
-
runtime.scope.abandon();
|
|
3963
|
-
},
|
|
3964
|
-
};
|
|
3849
|
+
return prepareRenderSystemRecoveryRoots(runtime, environmentLifecycle, frameState, (next) => {
|
|
3850
|
+
environmentLifecycle = next;
|
|
3851
|
+
});
|
|
3965
3852
|
},
|
|
3966
3853
|
};
|
|
3967
3854
|
}
|