@forgeax/engine-render 0.1.32 → 0.1.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1374 -142
- package/dist/assembly/analytic-fog-registration.d.ts +3 -0
- package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
- package/dist/assembly/backend-contract.d.ts +2 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
- package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
- package/dist/assembly/canvas-draw-guard.d.ts +3 -0
- package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
- package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
- package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
- package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
- package/dist/assembly/factory.d.ts +1 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/fxaa-registration.d.ts +4 -0
- package/dist/assembly/fxaa-registration.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +3 -3
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/lod-observation.d.ts +4 -0
- package/dist/assembly/lod-observation.d.ts.map +1 -0
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
- package/dist/assembly/material-shader-policy.d.ts +16 -2
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
- package/dist/assembly/motion-blur-registration.d.ts +3 -0
- package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/render-feature-post-processes.d.ts +6 -0
- package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
- package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-inspection.d.ts +11 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -1
- package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
- package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
- package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
- package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +2 -2
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/barrel-distortion.d.ts +47 -0
- package/dist/barrel-distortion.d.ts.map +1 -0
- package/dist/bloom-admission.d.ts +13 -0
- package/dist/bloom-admission.d.ts.map +1 -0
- package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
- package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
- package/dist/{chunk-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
- package/dist/chunk-HEB564WF.mjs.map +1 -0
- package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
- package/dist/chunk-MKDIT2EM.mjs.map +1 -0
- package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
- package/dist/{chunk-S665NJNF.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
- package/dist/chunk-ODZWR6JQ.mjs +4927 -0
- package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
- package/dist/{chunk-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
- package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
- package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
- package/dist/chunk-UI5SFODX.mjs.map +1 -0
- package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
- package/dist/chunk-UINHLCZA.mjs.map +1 -0
- package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
- package/dist/chunk-WEX45HKH.mjs.map +1 -0
- package/dist/cloud/density.d.ts +55 -0
- package/dist/cloud/density.d.ts.map +1 -0
- package/dist/cloud/extract.d.ts +25 -0
- package/dist/cloud/extract.d.ts.map +1 -0
- package/dist/cloud/feature.d.ts +57 -0
- package/dist/cloud/feature.d.ts.map +1 -0
- package/dist/cloud/frame-context.d.ts +8 -0
- package/dist/cloud/frame-context.d.ts.map +1 -0
- package/dist/cloud/inspection.d.ts +59 -0
- package/dist/cloud/inspection.d.ts.map +1 -0
- package/dist/cloud/optics.d.ts +56 -0
- package/dist/cloud/optics.d.ts.map +1 -0
- package/dist/cloud/parameters.d.ts +73 -0
- package/dist/cloud/parameters.d.ts.map +1 -0
- package/dist/cloud/resources.d.ts +60 -0
- package/dist/cloud/resources.d.ts.map +1 -0
- package/dist/cloud/shadow.d.ts +42 -0
- package/dist/cloud/shadow.d.ts.map +1 -0
- package/dist/cloud/temporal.d.ts +74 -0
- package/dist/cloud/temporal.d.ts.map +1 -0
- package/dist/components/atmosphere.d.ts +2 -0
- package/dist/components/atmosphere.d.ts.map +1 -1
- package/dist/components/barrel-distortion.d.ts +13 -0
- package/dist/components/barrel-distortion.d.ts.map +1 -0
- package/dist/components/camera.d.ts +20 -4
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/cloud-layer.d.ts +29 -0
- package/dist/components/cloud-layer.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +20 -6
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/components/mesh-filter.d.ts +6 -5
- package/dist/components/mesh-filter.d.ts.map +1 -1
- package/dist/components/motion-blur.d.ts +1 -0
- package/dist/components/motion-blur.d.ts.map +1 -1
- package/dist/construct-renderer.d.ts +1 -1
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +9751 -3528
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +6 -0
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/dynamic-geometry.d.ts +5 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/environment/analytic-fog.d.ts +6 -0
- package/dist/environment/analytic-fog.d.ts.map +1 -0
- package/dist/errors/cloud.d.ts +59 -0
- package/dist/errors/cloud.d.ts.map +1 -0
- package/dist/errors/render.d.ts +23 -5
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/examples/single-layer-medium-surface.d.ts +47 -0
- package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +12 -1
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/environment.d.ts +2 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/features/barrel-distortion.d.ts +29 -0
- package/dist/features/barrel-distortion.d.ts.map +1 -0
- package/dist/features/error-reporting.d.ts +17 -0
- package/dist/features/error-reporting.d.ts.map +1 -0
- package/dist/features/host.d.ts +15 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
- package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
- package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
- package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
- package/dist/features/plan.d.ts +15 -4
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +9 -5
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/render-graph-compute.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +5 -0
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +1 -0
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/targets.d.ts +2 -0
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +44 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +15 -7
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-dirty-ranges.d.ts +11 -0
- package/dist/gpu-dirty-ranges.d.ts.map +1 -0
- package/dist/gpu-driven/batch-topology.d.ts +17 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts +6 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts +7 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster-material.d.ts +178 -0
- package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +50 -4
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/resource-allocation.d.ts +31 -0
- package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
- package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
- package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +35 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +11 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +2 -2
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +10 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +31 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +258 -8
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +178 -3
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instance-buffer-cache.d.ts +4 -4
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +49 -94
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +7 -7
- package/dist/pbr-pipeline.d.ts +19 -1
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
- package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
- package/dist/pipeline/standard-output/types.d.ts +4 -2
- package/dist/pipeline/standard-output/types.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +28 -19
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +2 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/record/barrel-distortion-frame.d.ts +15 -0
- package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
- package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
- package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
- package/dist/record/fold-buckets.d.ts +95 -0
- package/dist/record/fold-buckets.d.ts.map +1 -0
- package/dist/record/fold-instance-buffer.d.ts +6 -0
- package/dist/record/fold-instance-buffer.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +1 -0
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +40 -3
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +14 -62
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-draw-receipts.d.ts +11 -0
- package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +8 -0
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +21 -5
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +13 -2
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +6 -5
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/motion-blur-receipt.d.ts +11 -0
- package/dist/record/motion-blur-receipt.d.ts.map +1 -0
- package/dist/record/probe-blend-buffer.d.ts +16 -0
- package/dist/record/probe-blend-buffer.d.ts.map +1 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +34 -31
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -0
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +6 -4
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +22 -2
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +11 -3
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/record/volume-params.d.ts +9 -0
- package/dist/record/volume-params.d.ts.map +1 -0
- package/dist/recovery/render-system-candidate.d.ts +10 -0
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +66 -8
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +106 -3
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +3 -2
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +24 -10
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-presentation.d.ts +23 -0
- package/dist/render-system-presentation.d.ts.map +1 -0
- package/dist/render-system-producer-roots.d.ts +10 -0
- package/dist/render-system-producer-roots.d.ts.map +1 -0
- package/dist/render-system-residency.d.ts +12 -0
- package/dist/render-system-residency.d.ts.map +1 -0
- package/dist/render-system.d.ts +26 -15
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/probe-blend.d.ts +27 -0
- package/dist/scene/probe-blend.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +14 -5
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +9 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/surface/dynamic-input.d.ts +133 -0
- package/dist/surface/dynamic-input.d.ts.map +1 -0
- package/dist/surface/gpu-driven.d.ts +41 -0
- package/dist/surface/gpu-driven.d.ts.map +1 -0
- package/dist/surface/submission-observation.d.ts +136 -0
- package/dist/surface/submission-observation.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +7 -0
- package/dist/temporal/frame.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts +13 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- package/dist/temporal/inspection.d.ts.map +1 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
- package/dist/temporal/view.d.ts +6 -1
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/transmission/single-layer-medium.d.ts +89 -0
- package/dist/transmission/single-layer-medium.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +24 -9
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +9 -5
- package/dist/volume/component.d.ts.map +1 -1
- package/dist/volume/extract.d.ts +1 -1
- package/dist/volume/extract.d.ts.map +1 -1
- package/dist/volume/inspection.d.ts +2 -0
- package/dist/volume/inspection.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +4 -1
- package/dist/volume/passes.d.ts.map +1 -1
- package/dist/volume/resources.d.ts.map +1 -1
- package/dist/volume/temporal.d.ts +3 -1
- package/dist/volume/temporal.d.ts.map +1 -1
- package/package.json +22 -21
- package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
- package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
- package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
- package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
- package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
- package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
- package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
- package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
- package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
- package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
- package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
- package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
- package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
- package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
- package/src/__tests__/environment-selection.unit.test.ts +12 -0
- package/src/__tests__/factory-contract.integration.test.ts +626 -113
- package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
- package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
- package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
- package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +2 -1
- package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
- package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +7 -6
- package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
- package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
- package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
- package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
- package/src/__tests__/gpu-scene.unit.test.ts +210 -9
- package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
- package/src/__tests__/instances-culling.integration.test.ts +10 -36
- package/src/__tests__/instances-store.unit.test.ts +105 -238
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
- package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
- package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
- package/src/__tests__/motion-blur-compute.dawn.test.ts +589 -0
- package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
- package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
- package/src/__tests__/probe-bindings.unit.test.ts +582 -1
- package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
- package/src/__tests__/public-surface.test-d.ts +8 -0
- package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +9 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
- package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
- package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
- package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
- package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
- package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +37 -6
- package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
- package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
- package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +33 -11
- package/src/__tests__/resource-allocation.unit.test.ts +123 -0
- package/src/__tests__/shader-manifest-fixture.ts +4 -4
- package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
- package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +17 -0
- package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
- package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
- package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
- package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
- package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
- package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
- package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
- package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
- package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
- package/src/__tests__/temporal-performance.integration.test.ts +3 -3
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
- package/src/__tests__/temporal-view.unit.test.ts +2 -1
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
- package/src/__tests__/visibility-instances.integration.test.ts +7 -19
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
- package/src/__tests__/volume-optics-oracle.unit.test.ts +7 -3
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
- package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
- package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
- package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +558 -68
- package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
- package/src/assembly/analytic-fog-registration.ts +14 -0
- package/src/assembly/backend-contract.ts +30 -0
- package/src/assembly/barrel-distortion-inspection.ts +22 -0
- package/src/assembly/canvas-draw-guard.ts +11 -0
- package/src/assembly/cloud-shadow-entry.ts +22 -0
- package/src/assembly/dynamic-geometry-host.ts +65 -37
- package/src/assembly/dynamic-geometry-runtime.ts +7 -1
- package/src/assembly/factory.ts +2 -30
- package/src/assembly/fxaa-registration.ts +17 -0
- package/src/assembly/host-contract.ts +3 -3
- package/src/assembly/lod-observation.ts +12 -0
- package/src/assembly/material/assembly.ts +25 -13
- package/src/assembly/material/pipeline-helpers.ts +53 -12
- package/src/assembly/material-shader-policy.ts +55 -0
- package/src/assembly/material-shader-prewarm.ts +21 -10
- package/src/assembly/motion-blur-registration.ts +17 -0
- package/src/assembly/recovery/device-loss-fanout.ts +13 -0
- package/src/assembly/recovery/renderer-recover.ts +41 -18
- package/src/assembly/render-feature-post-processes.ts +54 -0
- package/src/assembly/renderer-facade.ts +6 -1
- package/src/assembly/renderer-feature-inspection.ts +8 -2
- package/src/assembly/renderer-frame-transaction.ts +23 -0
- package/src/assembly/renderer-inspection.ts +28 -0
- package/src/assembly/skin-palette-owner.ts +1 -1
- package/src/assembly/temporal-post-process-prewarm.ts +40 -0
- package/src/assembly/webgpu-pbr-ready.ts +9 -1
- package/src/assembly/webgpu-ready-contract.ts +8 -3
- package/src/assembly/webgpu-ready-per-pass.ts +104 -0
- package/src/assembly/webgpu-ready.ts +296 -306
- package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
- package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
- package/src/assembly/webgpu-renderer.ts +228 -281
- package/src/assembly/webgpu-vertex-layouts.ts +1 -1
- package/src/barrel-distortion.ts +247 -0
- package/src/bloom-admission.ts +21 -0
- package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
- package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
- package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
- package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
- package/src/cloud/density.ts +600 -0
- package/src/cloud/extract.ts +110 -0
- package/src/cloud/feature.ts +1810 -0
- package/src/cloud/frame-context.ts +42 -0
- package/src/cloud/inspection.ts +130 -0
- package/src/cloud/optics.ts +285 -0
- package/src/cloud/parameters.ts +255 -0
- package/src/cloud/resources.ts +122 -0
- package/src/cloud/shadow.ts +167 -0
- package/src/cloud/temporal.ts +226 -0
- package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
- package/src/components/atmosphere.ts +4 -0
- package/src/components/barrel-distortion.ts +46 -0
- package/src/components/camera.ts +66 -10
- package/src/components/cloud-layer.ts +47 -0
- package/src/components/index.ts +2 -0
- package/src/components/instances.ts +18 -45
- package/src/components/mesh-filter.ts +11 -9
- package/src/components/motion-blur.ts +1 -0
- package/src/components/sprite-instances.ts +1 -1
- package/src/construct-renderer.ts +1 -1
- package/src/device/gpu-residency.ts +56 -12
- package/src/dynamic-geometry.ts +12 -1
- package/src/environment/analytic-fog.ts +44 -0
- package/src/environment/background.ts +2 -2
- package/src/errors/cloud.ts +103 -0
- package/src/errors/render.ts +58 -8
- package/src/examples/single-layer-medium-surface.ts +59 -0
- package/src/extract/camera.ts +35 -8
- package/src/extract/contracts.ts +12 -0
- package/src/extract/environment.ts +4 -0
- package/src/features/barrel-distortion.ts +172 -0
- package/src/features/error-reporting.ts +98 -0
- package/src/features/host.ts +138 -24
- package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
- package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
- package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
- package/src/features/motion-blur/motion-blur-params.ts +70 -2
- package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
- package/src/features/plan.ts +33 -8
- package/src/features/prepared-gpu-work.ts +86 -35
- package/src/features/render-graph-compute.ts +13 -5
- package/src/features/render-graph-contribution.ts +11 -0
- package/src/features/render-graph-raster.ts +45 -3
- package/src/features/targets.ts +66 -0
- package/src/features/types.ts +47 -0
- package/src/fullscreen-post-process-pass.ts +41 -9
- package/src/gpu-dirty-ranges.ts +48 -0
- package/src/gpu-driven/batch-topology.ts +53 -0
- package/src/gpu-driven/material-artifacts.ts +35 -32
- package/src/gpu-driven/prepared-draw.ts +27 -14
- package/src/gpu-driven/production-raster-material.ts +1894 -0
- package/src/gpu-driven/production-raster.ts +904 -787
- package/src/gpu-driven/resource-allocation.ts +142 -0
- package/src/gpu-driven/shadow-ownership.ts +71 -0
- package/src/gpu-driven/view-gpu.ts +181 -10
- package/src/gpu-scene.ts +259 -101
- package/src/hdrp-buffers.ts +4 -3
- package/src/ibl/skylight-bind-group.ts +49 -7
- package/src/index.ts +228 -9
- package/src/inspection-types.ts +222 -2
- package/src/instance-buffer-cache.ts +4 -4
- package/src/instances.ts +151 -492
- package/src/pbr-pipeline.ts +219 -13
- package/src/pipeline/single-layer-medium-passes.ts +267 -0
- package/src/pipeline/standard-forward-lane.ts +313 -57
- package/src/pipeline/standard-output/graph.ts +8 -2
- package/src/pipeline/standard-output/types.ts +12 -1
- package/src/pipeline/standard-pipeline.ts +291 -18
- package/src/pipeline/standard-post.ts +397 -102
- package/src/pipeline-builder.ts +1 -1
- package/src/pipeline-spec.ts +5 -5
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
- package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
- package/src/prepare/prepared-graphics-resolver.ts +2 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
- package/src/record/__tests__/temporal-payload.unit.test.ts +3 -2
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
- package/src/record/barrel-distortion-frame.ts +110 -0
- package/src/record/dynamic-geometry-consumption.ts +39 -9
- package/src/record/fold-buckets.ts +852 -0
- package/src/record/fold-instance-buffer.ts +51 -0
- package/src/record/frame-lighting.ts +36 -2
- package/src/record/frame-snapshot.ts +44 -4
- package/src/record/frame-targets.ts +10 -6
- package/src/record/frame.ts +373 -1099
- package/src/record/gpu-draw-receipts.ts +38 -0
- package/src/record/gpu-timing.ts +48 -5
- package/src/record/main-pass-geometry.ts +281 -83
- package/src/record/main-pass-material.ts +66 -4
- package/src/record/main-pass-sprite-draws.ts +13 -66
- package/src/record/main-pass.ts +156 -20
- package/src/record/mesh-ssbo.ts +43 -6
- package/src/record/motion-blur-receipt.ts +91 -0
- package/src/record/probe-blend-buffer.ts +180 -0
- package/src/record/recovery-pipeline.ts +35 -3
- package/src/record/render-context.ts +51 -31
- package/src/record/shadow-pass.ts +36 -2
- package/src/record/skybox-post-pass.ts +150 -200
- package/src/record/typed-frame-graph.ts +824 -44
- package/src/record/view-ubo.ts +26 -3
- package/src/record/volume-params.ts +225 -0
- package/src/recovery/render-system-candidate.ts +257 -52
- package/src/reflection/record-owner.ts +7 -3
- package/src/render-contract.ts +71 -8
- package/src/render-graph-primitives.ts +7 -1
- package/src/render-pipeline.ts +136 -1
- package/src/render-system-extract-tail.ts +72 -60
- package/src/render-system-extract.ts +117 -87
- package/src/render-system-presentation.ts +56 -0
- package/src/render-system-producer-roots.ts +96 -0
- package/src/render-system-residency.ts +159 -0
- package/src/render-system.ts +601 -482
- package/src/scene/probe-blend.ts +96 -4
- package/src/scene/render-scene.ts +431 -281
- package/src/ssao-buffers.ts +95 -2
- package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
- package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
- package/src/surface/dynamic-input.ts +658 -0
- package/src/surface/gpu-driven.ts +147 -0
- package/src/surface/submission-observation.ts +517 -0
- package/src/systems/skin-palette-allocator.ts +4 -1
- package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
- package/src/temporal/frame-coordinator.ts +8 -1
- package/src/temporal/frame.ts +20 -0
- package/src/temporal/gpu.ts +101 -17
- package/src/temporal/inspection.ts +7 -1
- package/src/temporal/standard-scene-data.ts +5 -0
- package/src/temporal/target-coverage-attachment.ts +4 -0
- package/src/temporal/view.ts +13 -2
- package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
- package/src/transmission/single-layer-medium.ts +322 -0
- package/src/typed-render-graph-primitives.ts +191 -50
- package/src/volume/component.ts +10 -10
- package/src/volume/extract.ts +11 -5
- package/src/volume/inspection.ts +3 -0
- package/src/volume/passes.ts +95 -8
- package/src/volume/resources.ts +2 -1
- package/src/volume/temporal.ts +11 -0
- package/dist/chunk-4NNZQCL3.mjs.map +0 -1
- package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
- package/dist/chunk-DRR7D3KX.mjs.map +0 -1
- package/dist/chunk-GWCEMDVR.mjs.map +0 -1
- package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
- package/dist/chunk-JRIPCMYC.mjs.map +0 -1
- package/dist/chunk-LULCA3OF.mjs +0 -1713
- package/dist/chunk-LULCA3OF.mjs.map +0 -1
- package/dist/chunk-PA5DRJNI.mjs.map +0 -1
package/src/render-system.ts
CHANGED
|
@@ -1,45 +1,28 @@
|
|
|
1
1
|
import { projectCaptureScene } from './capture/scene-projection';
|
|
2
2
|
import type { RenderSceneBounds } from './scene/render-scene-types';
|
|
3
|
-
// @forgeax/engine-runtime - RenderSystem main entry (D-S2 three-stage Extract ->
|
|
4
|
-
// Prepare -> Record + 4-tier error fan-out).
|
|
5
|
-
//
|
|
6
|
-
// Engine-internal phase: NOT registered to World schedule (AC-09);
|
|
7
|
-
// `Renderer.draw([world], { cameraOwner: 0, resourceOwner: 0 })` invokes once per frame. See `Renderer` JSDoc in
|
|
8
|
-
// `./render-contract.ts` for the public error/frame contract and AGENTS.md
|
|
9
|
-
// "ECS render bridge" section for the AI-user-facing contract.
|
|
10
|
-
//
|
|
11
|
-
// Stage carve-out (review round 1 finding #3 - 505 line cap fallback):
|
|
12
|
-
// - render-system.ts (this file) types + orchestration
|
|
13
|
-
// - render-system-extract.ts Extract ECS query phase + snapshot helpers
|
|
14
|
-
// - render-system-record.ts Prepare + Record GPU phase + matrix helpers
|
|
15
|
-
//
|
|
16
3
|
// @forgeax/engine-math is referenced through render-system-record.ts which builds
|
|
17
4
|
// view/proj matrices and worldFromLocal via `mat4.compose / .multiply /
|
|
18
5
|
// .invert` (charter proposition 5: no math reinvention; render-system.test.ts
|
|
19
6
|
// asserts `/@forgeax\/engine-math/` shows up in render-system.ts source).
|
|
20
7
|
|
|
21
|
-
import { numMipLevels
|
|
8
|
+
import { numMipLevels } from '@forgeax/engine-assets-runtime';
|
|
22
9
|
import { Time, type World } from '@forgeax/engine-ecs';
|
|
23
10
|
import type { RenderReadLease } from '@forgeax/engine-ecs/projection';
|
|
24
11
|
import type { RecorderSession } from '@forgeax/engine-profiler';
|
|
25
12
|
import type { CompiledRenderGraphInfo } from '@forgeax/engine-render-graph';
|
|
26
13
|
import type { BindGroupLayout, Buffer, RenderPipeline, RhiDevice } from '@forgeax/engine-rhi';
|
|
27
14
|
import { err, ok, type Result, RhiError } from '@forgeax/engine-rhi';
|
|
28
|
-
import {
|
|
29
|
-
deriveTextureLayout,
|
|
30
|
-
type MaterialAsset,
|
|
31
|
-
type RenderPipelineAsset,
|
|
32
|
-
type SamplerAsset,
|
|
33
|
-
type TextureAsset,
|
|
34
|
-
toShared,
|
|
35
|
-
} from '@forgeax/engine-types';
|
|
15
|
+
import { type RenderPipelineAsset, toShared } from '@forgeax/engine-types';
|
|
36
16
|
import {
|
|
37
17
|
type DirectionalShadowInspectionSource,
|
|
38
18
|
directionalShadowProfileFromQuality,
|
|
39
19
|
projectDirectionalShadowInspectionSource,
|
|
40
20
|
} from './assembly/directional-shadow-inspection';
|
|
41
21
|
import { createGpuDrivenOwner } from './assembly/gpu-driven-owner';
|
|
22
|
+
import { standardBloomAdmitted } from './bloom-admission';
|
|
23
|
+
import { createCloudFeatureFrameContext, createCloudFeatureView } from './cloud/frame-context';
|
|
42
24
|
import { createClusterBinScratch } from './cluster-binner';
|
|
25
|
+
import type { DynamicGeometryRecordStageLane } from './dynamic-geometry';
|
|
43
26
|
import { EnvironmentLifecycle } from './environment/lifecycle';
|
|
44
27
|
import {
|
|
45
28
|
type ObservationUnavailableError,
|
|
@@ -48,11 +31,25 @@ import {
|
|
|
48
31
|
} from './errors/render';
|
|
49
32
|
import { projectDepthOfFieldInspection } from './features/depth-of-field/depth-of-field-inspection';
|
|
50
33
|
import { resolveDepthOfFieldFrameParams } from './features/depth-of-field/depth-of-field-params';
|
|
34
|
+
import type { PendingRenderFeatureErrorReport } from './features/error-reporting';
|
|
35
|
+
import { reportPendingRenderFeatureErrors } from './features/error-reporting';
|
|
51
36
|
import {
|
|
52
37
|
type RenderFeaturePreparedGraphicsResolverInput,
|
|
53
38
|
runRenderFeatureFrame,
|
|
54
39
|
settlePreparedGraphicsCompletion,
|
|
55
40
|
} from './features/host';
|
|
41
|
+
import {
|
|
42
|
+
createMotionBlurFeature,
|
|
43
|
+
type MotionBlurFeatureInput,
|
|
44
|
+
} from './features/motion-blur/motion-blur-feature';
|
|
45
|
+
import {
|
|
46
|
+
MotionBlurValidationError,
|
|
47
|
+
motionBlurTemporalDemand,
|
|
48
|
+
} from './features/motion-blur/motion-blur-params';
|
|
49
|
+
import {
|
|
50
|
+
planMotionBlurFrame,
|
|
51
|
+
projectMotionBlurInspection,
|
|
52
|
+
} from './features/motion-blur/motion-blur-runtime';
|
|
56
53
|
import { createFeatureNoiseResolver } from './features/noise-texture';
|
|
57
54
|
import {
|
|
58
55
|
createRenderFeatureGpuWorkOwner,
|
|
@@ -69,6 +66,7 @@ import {
|
|
|
69
66
|
postProcessShaderPipelineLabel,
|
|
70
67
|
} from './fullscreen-post-process-pass';
|
|
71
68
|
import type {
|
|
69
|
+
BarrelDistortionInspection,
|
|
72
70
|
BloomInspection,
|
|
73
71
|
DepthOfFieldInspection,
|
|
74
72
|
DirectionalShadowInspection,
|
|
@@ -83,6 +81,7 @@ import type {
|
|
|
83
81
|
TemporalTargetInspection,
|
|
84
82
|
TransmissionInspection,
|
|
85
83
|
} from './inspection-types';
|
|
84
|
+
import { emptyBloomInspection } from './inspection-types';
|
|
86
85
|
import { buildOcclusionProxyVertices } from './occlusion-proxy';
|
|
87
86
|
import {
|
|
88
87
|
AUTO_EXPOSURE_HISTOGRAM_BYTES,
|
|
@@ -110,11 +109,7 @@ import {
|
|
|
110
109
|
} from './pipeline/standard-output/resources';
|
|
111
110
|
import type { PointsLinesRetainedSnapshot } from './points-lines/snapshot';
|
|
112
111
|
import { StandardPointsLinesOwner } from './points-lines/standard-owner';
|
|
113
|
-
import {
|
|
114
|
-
createRenderSystemRecovery,
|
|
115
|
-
materialSamplerHandles,
|
|
116
|
-
materialTextureHandles,
|
|
117
|
-
} from './recovery/render-system-candidate';
|
|
112
|
+
import { createRenderSystemRecovery } from './recovery/render-system-candidate';
|
|
118
113
|
|
|
119
114
|
export { materialTextureHandlesForResidency } from './recovery/render-system-candidate';
|
|
120
115
|
|
|
@@ -154,9 +149,10 @@ import { inspectVolumetricFog } from './volume/inspection';
|
|
|
154
149
|
|
|
155
150
|
export type { RenderSceneInspection } from './inspection-types';
|
|
156
151
|
|
|
152
|
+
import type { BarrelDistortionMapping } from './barrel-distortion';
|
|
157
153
|
import { createCubeCaptureScheduler } from './capture/scheduler';
|
|
158
154
|
import type { EnvironmentInspection } from './environment/inspection';
|
|
159
|
-
import {
|
|
155
|
+
import { rebaseShadowCasterOwnership } from './gpu-driven/shadow-ownership';
|
|
160
156
|
import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from './gpu-usage';
|
|
161
157
|
import { resetHdrpBuffers } from './hdrp-buffers';
|
|
162
158
|
import type { SkylightBindGroupResources } from './ibl/skylight-bind-group';
|
|
@@ -166,11 +162,9 @@ import {
|
|
|
166
162
|
disposeTransientInstanceBuffers,
|
|
167
163
|
} from './instance-buffer-cache';
|
|
168
164
|
import type { InstanceCollectionInspection } from './instances';
|
|
169
|
-
import {
|
|
165
|
+
import { InstanceProjectionStore } from './instances';
|
|
170
166
|
import {
|
|
171
167
|
type MeshMaterialBindingObservation,
|
|
172
|
-
type MeshMaterialBindingPreparationFailure,
|
|
173
|
-
type MeshMaterialBindingResidency,
|
|
174
168
|
projectMeshMaterialBindingObservation,
|
|
175
169
|
} from './mesh-material-bindings';
|
|
176
170
|
import type { StandardLightingInspection } from './pipeline/standard-lighting/inspection';
|
|
@@ -183,6 +177,10 @@ import {
|
|
|
183
177
|
createPreparedGraphicsResolver,
|
|
184
178
|
type PreparedGraphicsResolver,
|
|
185
179
|
} from './prepare/prepared-graphics-resolver';
|
|
180
|
+
import {
|
|
181
|
+
inspectBarrelDistortionState,
|
|
182
|
+
resetBarrelDistortionGraphState,
|
|
183
|
+
} from './record/barrel-distortion-frame';
|
|
186
184
|
import {
|
|
187
185
|
type CubeCaptureFrameInput,
|
|
188
186
|
type FrameObservation,
|
|
@@ -198,6 +196,7 @@ import type {
|
|
|
198
196
|
RenderFrameState,
|
|
199
197
|
} from './record/frame-snapshot';
|
|
200
198
|
import { getTextureIdentity, worldEntityKey } from './record/frame-snapshot';
|
|
199
|
+
import type { RenderableDrawReceipt } from './record/gpu-draw-receipts';
|
|
201
200
|
import type { GpuPassTimingReason } from './record/gpu-pass-timing/errors';
|
|
202
201
|
import type {
|
|
203
202
|
GpuPassTimingCapture,
|
|
@@ -215,34 +214,39 @@ import type { PipelineState, RenderSystemInternals } from './record/render-conte
|
|
|
215
214
|
import type { CubeCaptureGraphState } from './record/typed-frame-graph';
|
|
216
215
|
import {
|
|
217
216
|
getRenderFeatureGraphInspection,
|
|
217
|
+
inspectRenderGraphGenerationAllocation,
|
|
218
218
|
type RenderFeatureGraphCandidate,
|
|
219
219
|
recordRenderFeatureCandidate,
|
|
220
220
|
resetRenderFeatureGraphState,
|
|
221
|
+
retire as retireCompiledGraph,
|
|
222
|
+
settleBarrelDistortionGraphCandidate,
|
|
221
223
|
settleDepthOfFieldGraphCandidate,
|
|
222
224
|
settleVolumetricFogGraphCandidate,
|
|
223
225
|
} from './record/typed-frame-graph';
|
|
224
226
|
import {
|
|
225
227
|
type CameraSnapshot,
|
|
226
228
|
type DrawOwnerOptions,
|
|
229
|
+
type FramePresentation,
|
|
227
230
|
RENDER_PHASE_CATALOG,
|
|
228
231
|
type RenderPhase,
|
|
229
232
|
type RenderPhaseSkipReason,
|
|
230
233
|
type RenderRecordPhase,
|
|
231
234
|
} from './render-contract';
|
|
232
|
-
import type {
|
|
233
|
-
DispatchEntry,
|
|
234
|
-
ExtractedLights,
|
|
235
|
-
MaterialSnapshot,
|
|
236
|
-
RenderableSnapshot,
|
|
237
|
-
ShadowCasterMembership,
|
|
238
|
-
} from './render-system-extract';
|
|
235
|
+
import type { DispatchEntry, ExtractedLights, RenderableSnapshot } from './render-system-extract';
|
|
239
236
|
import { extractFrames } from './render-system-extract';
|
|
237
|
+
import { projectFramePresentation } from './render-system-presentation';
|
|
238
|
+
import {
|
|
239
|
+
createRendererProducerRootMatrix,
|
|
240
|
+
type RendererProducerRoot,
|
|
241
|
+
} from './render-system-producer-roots';
|
|
240
242
|
import {
|
|
241
243
|
canonicalizeWorldComposition,
|
|
242
244
|
createLodWorldInspections,
|
|
243
245
|
} from './render-system-projections';
|
|
246
|
+
import { observeMaterialResidency } from './render-system-residency';
|
|
244
247
|
import { PersistentRenderScene } from './scene/render-scene';
|
|
245
248
|
import { inspectLodOcclusion } from './scene/visibility/inspection';
|
|
249
|
+
import { resetSsaoResources } from './ssao-buffers';
|
|
246
250
|
import { resolveSsaoParameters } from './ssao-config';
|
|
247
251
|
import {
|
|
248
252
|
projectSsrDependencies,
|
|
@@ -251,6 +255,8 @@ import {
|
|
|
251
255
|
zeroSsrAdmissionWork,
|
|
252
256
|
} from './ssr/admission';
|
|
253
257
|
import { projectSsrSpatialInspection } from './ssr/inspection';
|
|
258
|
+
import type { SurfaceDynamicInputFrame } from './surface/dynamic-input';
|
|
259
|
+
import { SurfaceSubmissionObservationOwner } from './surface/submission-observation';
|
|
254
260
|
import { sortTransparentDispatch } from './systems/transparent-dispatch';
|
|
255
261
|
import type { RenderTarget } from './targets/contracts';
|
|
256
262
|
import { createTemporalFrameTransaction, type TemporalFrame } from './temporal/frame';
|
|
@@ -268,73 +274,6 @@ import {
|
|
|
268
274
|
inspectTransmissionFromAdmission,
|
|
269
275
|
} from './transmission/inspection';
|
|
270
276
|
|
|
271
|
-
const WORLD_ENTITY_KEY_STRIDE = 4294967296;
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Extract emits world/entity keys in the transient `worlds[]` index domain,
|
|
275
|
-
* while PersistentRenderScene owns stable renderer-local World keys for the
|
|
276
|
-
* retained GPU scene. Rebase ShadowCaster ownership at this orchestration
|
|
277
|
-
* boundary before both GPU projection and CPU residual recording consume it.
|
|
278
|
-
*/
|
|
279
|
-
function rebaseShadowCasterOwnership(
|
|
280
|
-
worlds: readonly World[],
|
|
281
|
-
stableWorldKeys: readonly number[],
|
|
282
|
-
entityKeys: ReadonlySet<number>,
|
|
283
|
-
drawKeys: ReadonlySet<string>,
|
|
284
|
-
membership: readonly ShadowCasterMembership[] | undefined,
|
|
285
|
-
): {
|
|
286
|
-
readonly entityKeys: ReadonlySet<number>;
|
|
287
|
-
readonly drawKeys: ReadonlySet<string>;
|
|
288
|
-
readonly membership: readonly ShadowCasterMembership[] | undefined;
|
|
289
|
-
} {
|
|
290
|
-
const rebaseWorldEntity = (composite: number): number => {
|
|
291
|
-
const transientWorldId = Math.floor(composite / WORLD_ENTITY_KEY_STRIDE);
|
|
292
|
-
if (
|
|
293
|
-
!Number.isInteger(transientWorldId) ||
|
|
294
|
-
transientWorldId < 0 ||
|
|
295
|
-
transientWorldId >= worlds.length
|
|
296
|
-
) {
|
|
297
|
-
return composite;
|
|
298
|
-
}
|
|
299
|
-
const entityKey = composite - transientWorldId * WORLD_ENTITY_KEY_STRIDE;
|
|
300
|
-
return worldEntityKey(stableWorldKeys[transientWorldId] ?? transientWorldId, entityKey);
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
const stableMembership =
|
|
304
|
-
membership === undefined
|
|
305
|
-
? undefined
|
|
306
|
-
: membership.map((entry) => ({
|
|
307
|
-
...entry,
|
|
308
|
-
worldEntity: rebaseWorldEntity(entry.worldEntity),
|
|
309
|
-
}));
|
|
310
|
-
const stableDrawKeys =
|
|
311
|
-
stableMembership === undefined
|
|
312
|
-
? new Set(
|
|
313
|
-
[...drawKeys].map((key) => {
|
|
314
|
-
const parts = key.split(':');
|
|
315
|
-
if (parts.length !== 4) return key;
|
|
316
|
-
const transientWorldEntity = Number(parts[0]);
|
|
317
|
-
if (!Number.isFinite(transientWorldEntity)) return key;
|
|
318
|
-
return `${rebaseWorldEntity(transientWorldEntity)}:${parts[1]}:${parts[2]}:${parts[3]}`;
|
|
319
|
-
}),
|
|
320
|
-
)
|
|
321
|
-
: new Set(
|
|
322
|
-
stableMembership.map((entry) =>
|
|
323
|
-
gpuDrivenShadowDrawKey(
|
|
324
|
-
entry.worldEntity,
|
|
325
|
-
entry.materialHandle,
|
|
326
|
-
entry.drawItemIndex,
|
|
327
|
-
entry.passIndex,
|
|
328
|
-
),
|
|
329
|
-
),
|
|
330
|
-
);
|
|
331
|
-
return {
|
|
332
|
-
entityKeys: new Set([...entityKeys].map(rebaseWorldEntity)),
|
|
333
|
-
drawKeys: stableDrawKeys,
|
|
334
|
-
membership: stableMembership,
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
|
|
338
277
|
type TimingSessionHost = RenderSystemInternals & {
|
|
339
278
|
gpuPassTimingSession?: GpuPassTimingSession | undefined;
|
|
340
279
|
gpuPassTimingCapture?: GpuPassTimingCapture | undefined;
|
|
@@ -371,102 +310,11 @@ export {
|
|
|
371
310
|
selectSwapChainFormat,
|
|
372
311
|
} from './record/render-context';
|
|
373
312
|
|
|
374
|
-
export type
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
| 'gpu-driven'
|
|
380
|
-
| 'feature'
|
|
381
|
-
| 'external-source'
|
|
382
|
-
| 'render-graph'
|
|
383
|
-
| 'target-history'
|
|
384
|
-
| 'observation-lease';
|
|
385
|
-
|
|
386
|
-
export interface RendererProducerRoot {
|
|
387
|
-
readonly kind: RendererProducerRootKind;
|
|
388
|
-
readonly owner: string;
|
|
389
|
-
readonly candidateScope: 'device-scope';
|
|
390
|
-
readonly visibility: 'visible-workset' | 'non-visible-lazy';
|
|
391
|
-
readonly disabledWork: 'zero' | 'lazy';
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const PRODUCER_ROOT_MATRIX: readonly RendererProducerRoot[] = Object.freeze([
|
|
395
|
-
{
|
|
396
|
-
kind: 'backend-surface',
|
|
397
|
-
owner: 'backend-surface-owner',
|
|
398
|
-
candidateScope: 'device-scope',
|
|
399
|
-
visibility: 'visible-workset',
|
|
400
|
-
disabledWork: 'zero',
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
kind: 'shader-material-pipeline',
|
|
404
|
-
owner: 'shader-material-pipeline-owner',
|
|
405
|
-
candidateScope: 'device-scope',
|
|
406
|
-
visibility: 'visible-workset',
|
|
407
|
-
disabledWork: 'zero',
|
|
408
|
-
},
|
|
409
|
-
{
|
|
410
|
-
kind: 'mesh-texture-sampler',
|
|
411
|
-
owner: 'gpu-residency',
|
|
412
|
-
candidateScope: 'device-scope',
|
|
413
|
-
visibility: 'visible-workset',
|
|
414
|
-
disabledWork: 'lazy',
|
|
415
|
-
},
|
|
416
|
-
{
|
|
417
|
-
kind: 'render-scene',
|
|
418
|
-
owner: 'persistent-render-scene',
|
|
419
|
-
candidateScope: 'device-scope',
|
|
420
|
-
visibility: 'visible-workset',
|
|
421
|
-
disabledWork: 'zero',
|
|
422
|
-
},
|
|
423
|
-
{
|
|
424
|
-
kind: 'gpu-driven',
|
|
425
|
-
owner: 'gpu-driven-production',
|
|
426
|
-
candidateScope: 'device-scope',
|
|
427
|
-
visibility: 'visible-workset',
|
|
428
|
-
disabledWork: 'zero',
|
|
429
|
-
},
|
|
430
|
-
{
|
|
431
|
-
kind: 'feature',
|
|
432
|
-
owner: 'render-feature-host',
|
|
433
|
-
candidateScope: 'device-scope',
|
|
434
|
-
visibility: 'visible-workset',
|
|
435
|
-
disabledWork: 'lazy',
|
|
436
|
-
},
|
|
437
|
-
{
|
|
438
|
-
kind: 'external-source',
|
|
439
|
-
owner: 'external-source-owner',
|
|
440
|
-
candidateScope: 'device-scope',
|
|
441
|
-
visibility: 'non-visible-lazy',
|
|
442
|
-
disabledWork: 'zero',
|
|
443
|
-
},
|
|
444
|
-
{
|
|
445
|
-
kind: 'render-graph',
|
|
446
|
-
owner: 'typed-frame-graph',
|
|
447
|
-
candidateScope: 'device-scope',
|
|
448
|
-
visibility: 'visible-workset',
|
|
449
|
-
disabledWork: 'zero',
|
|
450
|
-
},
|
|
451
|
-
{
|
|
452
|
-
kind: 'target-history',
|
|
453
|
-
owner: 'temporal-target-owner',
|
|
454
|
-
candidateScope: 'device-scope',
|
|
455
|
-
visibility: 'visible-workset',
|
|
456
|
-
disabledWork: 'zero',
|
|
457
|
-
},
|
|
458
|
-
{
|
|
459
|
-
kind: 'observation-lease',
|
|
460
|
-
owner: 'render-observation-owner',
|
|
461
|
-
candidateScope: 'device-scope',
|
|
462
|
-
visibility: 'non-visible-lazy',
|
|
463
|
-
disabledWork: 'zero',
|
|
464
|
-
},
|
|
465
|
-
]);
|
|
466
|
-
|
|
467
|
-
export function createRendererProducerRootMatrix(): readonly RendererProducerRoot[] {
|
|
468
|
-
return PRODUCER_ROOT_MATRIX;
|
|
469
|
-
}
|
|
313
|
+
export type {
|
|
314
|
+
RendererProducerRoot,
|
|
315
|
+
RendererProducerRootKind,
|
|
316
|
+
} from './render-system-producer-roots';
|
|
317
|
+
export { createRendererProducerRootMatrix } from './render-system-producer-roots';
|
|
470
318
|
|
|
471
319
|
/**
|
|
472
320
|
* Production-owned recovery facts. These values are projections of the live
|
|
@@ -505,6 +353,8 @@ export interface RecoveryProductionEvidence {
|
|
|
505
353
|
*/
|
|
506
354
|
export interface RenderSystem {
|
|
507
355
|
bounds(world: World, entity: number): RenderSceneBounds | undefined;
|
|
356
|
+
/** Publish one renderer-owned read-only Surface dynamic page for the next frame. */
|
|
357
|
+
setSurfaceDynamicInput(frame: SurfaceDynamicInputFrame | undefined): void;
|
|
508
358
|
/** Complete explicit SSR capability preparation before drawing a device generation. */
|
|
509
359
|
initializeSsr(device?: RhiDevice): Promise<void>;
|
|
510
360
|
/** Returns true only when this invocation reached queue submission. */
|
|
@@ -520,6 +370,11 @@ export interface RenderSystem {
|
|
|
520
370
|
* barrier; ECS component presence alone is not a draw receipt.
|
|
521
371
|
*/
|
|
522
372
|
isDynamicGeometryConsumed(world: World, entity: number, meshHandle: number | undefined): boolean;
|
|
373
|
+
dynamicGeometryRecordStageLane(
|
|
374
|
+
world: World,
|
|
375
|
+
entity: number,
|
|
376
|
+
meshHandle: number | undefined,
|
|
377
|
+
): DynamicGeometryRecordStageLane | undefined;
|
|
523
378
|
invalidateGeometryHistory(): void;
|
|
524
379
|
/** Prepare a detached graph candidate without entering the frame record path. */
|
|
525
380
|
prepareRecoveryGraphCandidate(
|
|
@@ -542,7 +397,10 @@ export interface RenderSystem {
|
|
|
542
397
|
options: FrameObservationOptions,
|
|
543
398
|
): Promise<Result<FrameObservation, ObservationUnavailableError>>;
|
|
544
399
|
/** Resolve the renderer-owned GPU LOD counters for the last accepted submit. */
|
|
545
|
-
observeLodOcclusion(
|
|
400
|
+
observeLodOcclusion(receipt?: {
|
|
401
|
+
readonly frameId: number;
|
|
402
|
+
readonly deviceGeneration: number;
|
|
403
|
+
}): Promise<void>;
|
|
546
404
|
/** Internal same-frame graph target access for backend diagnostics. */
|
|
547
405
|
getCurrentGraphTarget(name: string): CurrentGraphTarget | undefined;
|
|
548
406
|
/** Internal test capture copied into the draw's command submission. */
|
|
@@ -550,8 +408,6 @@ export interface RenderSystem {
|
|
|
550
408
|
readonly pipelineDispatchCounts: {
|
|
551
409
|
readonly unlit: number;
|
|
552
410
|
};
|
|
553
|
-
/** Renderer-owned source for explicit large instance collections. */
|
|
554
|
-
readonly instances: InstanceCollectionStore;
|
|
555
411
|
/** Detached residency and upload facts for explicit instance collections. */
|
|
556
412
|
readonly instanceCollectionsInspection: readonly InstanceCollectionInspection[];
|
|
557
413
|
/**
|
|
@@ -570,6 +426,8 @@ export interface RenderSystem {
|
|
|
570
426
|
readonly ssr: SsrSpatialInspection;
|
|
571
427
|
/** Producer completion fence included in the public FrameReceipt. */
|
|
572
428
|
readonly reflectionFallbackCompletion: Promise<void> | undefined;
|
|
429
|
+
/** Presentation readiness derived from the producer facts used by draw(). */
|
|
430
|
+
readonly presentation: FramePresentation;
|
|
573
431
|
/** True while a progressive CubeCamera candidate still owns unfinished faces. */
|
|
574
432
|
isCubeCapturePending(target: RenderTarget): boolean;
|
|
575
433
|
readonly environment: EnvironmentInspection;
|
|
@@ -580,6 +438,8 @@ export interface RenderSystem {
|
|
|
580
438
|
readonly temporal: TemporalInspection;
|
|
581
439
|
readonly bloom: BloomInspection;
|
|
582
440
|
readonly motionBlurInspection: MotionBlurInspection | undefined;
|
|
441
|
+
/** The last extraction validation failure, preserved for public draw(). */
|
|
442
|
+
readonly motionBlurInvalidParams: MotionBlurValidationError | undefined;
|
|
583
443
|
readonly depthOfFieldInspection: DepthOfFieldInspection | undefined;
|
|
584
444
|
readonly temporalTargetInspection: TemporalTargetInspection | undefined;
|
|
585
445
|
readonly lodOcclusionInspection: LodOcclusionInspection | undefined;
|
|
@@ -610,8 +470,14 @@ export interface RenderSystem {
|
|
|
610
470
|
readonly perFramePassNames: readonly string[];
|
|
611
471
|
/** Camera antialias mode for the last successfully submitted frame. */
|
|
612
472
|
readonly lastSuccessfulCameraAntialias: CameraSnapshot['antialias'] | undefined;
|
|
473
|
+
/** Effective output mapping for the last successfully submitted camera. */
|
|
474
|
+
readonly lastSuccessfulBarrelDistortion: BarrelDistortionMapping | undefined;
|
|
475
|
+
/** Detached accepted/LKG projection for Renderer.inspect(). */
|
|
476
|
+
readonly barrelDistortionInspection: BarrelDistortionInspection;
|
|
613
477
|
/** Detached compiled-graph facts used by the renderer inspection owner. */
|
|
614
478
|
readonly perFrameGraphInfo: CompiledRenderGraphInfo | undefined;
|
|
479
|
+
/** Detached allocation facts across active, candidate, and retiring graphs. */
|
|
480
|
+
readonly renderGraphGenerationAllocation: import('@forgeax/engine-render-graph').RenderGraphGenerationAllocationInspection;
|
|
615
481
|
/** Detached feature signature/compile/lifetime counters. */
|
|
616
482
|
readonly featureGraphInspection: import('./inspection-types').RenderFeatureGraphInspection;
|
|
617
483
|
/** Detached material texture-source probe counters from the last extract. */
|
|
@@ -723,13 +589,6 @@ function reportPreparedGraphicsCompletionError(
|
|
|
723
589
|
);
|
|
724
590
|
}
|
|
725
591
|
|
|
726
|
-
function isPendingRenderFeaturePreparation(error: RenderError): boolean {
|
|
727
|
-
return (
|
|
728
|
-
error.code === 'render-feature-preparation-failed' &&
|
|
729
|
-
error.detail.reason.startsWith('rhi-not-available:')
|
|
730
|
-
);
|
|
731
|
-
}
|
|
732
|
-
|
|
733
592
|
function makePreparedPipelinePendingError(): RhiError {
|
|
734
593
|
return new RhiError({
|
|
735
594
|
code: 'rhi-not-available',
|
|
@@ -738,149 +597,6 @@ function makePreparedPipelinePendingError(): RhiError {
|
|
|
738
597
|
});
|
|
739
598
|
}
|
|
740
599
|
|
|
741
|
-
function preparationFailureFrom(error: unknown): MeshMaterialBindingPreparationFailure | undefined {
|
|
742
|
-
if (typeof error !== 'object' || error === null) return undefined;
|
|
743
|
-
const value = error as {
|
|
744
|
-
readonly code?: unknown;
|
|
745
|
-
readonly expected?: unknown;
|
|
746
|
-
readonly hint?: unknown;
|
|
747
|
-
readonly detail?: unknown;
|
|
748
|
-
};
|
|
749
|
-
if (
|
|
750
|
-
typeof value.code !== 'string' ||
|
|
751
|
-
typeof value.expected !== 'string' ||
|
|
752
|
-
typeof value.hint !== 'string'
|
|
753
|
-
) {
|
|
754
|
-
return undefined;
|
|
755
|
-
}
|
|
756
|
-
const detail =
|
|
757
|
-
typeof value.detail === 'object' && value.detail !== null
|
|
758
|
-
? { ...(value.detail as Record<string, unknown>) }
|
|
759
|
-
: undefined;
|
|
760
|
-
return {
|
|
761
|
-
code: value.code,
|
|
762
|
-
expected: value.expected,
|
|
763
|
-
hint: value.hint,
|
|
764
|
-
...(detail === undefined ? {} : { detail }),
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
/**
|
|
769
|
-
* Project the producer-owned material and GPU store state into the one
|
|
770
|
-
* renderer observation surface. This is intentionally recomputed from the
|
|
771
|
-
* current frame's detached material snapshots; no readiness map is retained
|
|
772
|
-
* by RenderSystem. A producer failure with an already resident resource is
|
|
773
|
-
* reported as last-known-good, preserving recovery context without copying
|
|
774
|
-
* the producer's lifecycle state.
|
|
775
|
-
*/
|
|
776
|
-
function observeMaterialResidency(
|
|
777
|
-
world: World | undefined,
|
|
778
|
-
material: MaterialSnapshot,
|
|
779
|
-
internals: RenderSystemInternals,
|
|
780
|
-
): MeshMaterialBindingResidency {
|
|
781
|
-
const textures: Array<{ readonly handle: number; readonly mipLevelCount: number }> = [];
|
|
782
|
-
const samplers: Array<{ readonly handle: number; readonly resident: boolean }> = [];
|
|
783
|
-
let pending = false;
|
|
784
|
-
let resident = false;
|
|
785
|
-
let failure: MeshMaterialBindingPreparationFailure | undefined;
|
|
786
|
-
const keepFailure = (error: unknown): void => {
|
|
787
|
-
if (failure === undefined) failure = preparationFailureFrom(error);
|
|
788
|
-
};
|
|
789
|
-
|
|
790
|
-
if (world === undefined) {
|
|
791
|
-
pending = true;
|
|
792
|
-
} else {
|
|
793
|
-
const materialHandle = material.materialHandle;
|
|
794
|
-
if (materialHandle !== undefined && materialHandle !== 0) {
|
|
795
|
-
const materialResult = resolveAssetHandle<MaterialAsset>(
|
|
796
|
-
world,
|
|
797
|
-
toShared<'MaterialAsset'>(materialHandle),
|
|
798
|
-
);
|
|
799
|
-
if (!materialResult.ok) {
|
|
800
|
-
keepFailure(materialResult.error);
|
|
801
|
-
} else {
|
|
802
|
-
const guid = internals.assets.guidOf(materialResult.value);
|
|
803
|
-
if (guid !== undefined) {
|
|
804
|
-
const readiness = internals.assets.getMaterialReadiness(guid);
|
|
805
|
-
if (readiness?.status === 'Error') keepFailure(readiness.error);
|
|
806
|
-
const load = internals.assets.loadState.get(guid);
|
|
807
|
-
if (load?.status === 'provisional') pending = true;
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
for (const handle of materialTextureHandles(material)) {
|
|
813
|
-
const existing = internals.gpuStore.getTextureGpuView(handle, world);
|
|
814
|
-
const pod = resolveAssetHandle<TextureAsset>(world, handle);
|
|
815
|
-
if (!pod.ok) {
|
|
816
|
-
keepFailure(pod.error);
|
|
817
|
-
continue;
|
|
818
|
-
}
|
|
819
|
-
let view = existing;
|
|
820
|
-
if (view === undefined) {
|
|
821
|
-
const prepared = internals.gpuStore.ensureResident(handle, pod.value, world);
|
|
822
|
-
if (!prepared.ok) keepFailure(prepared.error);
|
|
823
|
-
view = internals.gpuStore.getTextureGpuView(handle, world);
|
|
824
|
-
}
|
|
825
|
-
if (view === undefined) {
|
|
826
|
-
pending = failure === undefined;
|
|
827
|
-
continue;
|
|
828
|
-
}
|
|
829
|
-
const textureLayout = deriveTextureLayout({
|
|
830
|
-
shape: pod.value.shape,
|
|
831
|
-
format: pod.value.format,
|
|
832
|
-
mips: pod.value.mips,
|
|
833
|
-
});
|
|
834
|
-
if (!textureLayout.ok) {
|
|
835
|
-
keepFailure(textureLayout.error);
|
|
836
|
-
continue;
|
|
837
|
-
}
|
|
838
|
-
resident = true;
|
|
839
|
-
textures.push({
|
|
840
|
-
handle: Number(handle),
|
|
841
|
-
mipLevelCount: Math.max(1, textureLayout.value.levels.length),
|
|
842
|
-
});
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
for (const handle of materialSamplerHandles(material)) {
|
|
846
|
-
const pod = resolveAssetHandle<SamplerAsset>(world, handle);
|
|
847
|
-
if (!pod.ok) {
|
|
848
|
-
keepFailure(pod.error);
|
|
849
|
-
samplers.push({ handle: Number(handle), resident: false });
|
|
850
|
-
continue;
|
|
851
|
-
}
|
|
852
|
-
const prepared = internals.gpuStore.ensureSamplerResident(handle, pod.value, world);
|
|
853
|
-
if (!prepared.ok) {
|
|
854
|
-
keepFailure(prepared.error);
|
|
855
|
-
samplers.push({ handle: Number(handle), resident: false });
|
|
856
|
-
} else {
|
|
857
|
-
resident = true;
|
|
858
|
-
samplers.push({ handle: Number(handle), resident: true });
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
// Video views are supplied by the dynamic host store at record time. They
|
|
862
|
-
// are not static TextureAsset residents, so this bounded projection stays
|
|
863
|
-
// pending until a dynamic observation contract exists rather than guessing
|
|
864
|
-
// from the VideoAsset GUID.
|
|
865
|
-
if ((material.videoTextureFields?.size ?? 0) > 0) pending = true;
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
const readiness =
|
|
869
|
-
failure === undefined
|
|
870
|
-
? pending
|
|
871
|
-
? 'pending'
|
|
872
|
-
: 'ready'
|
|
873
|
-
: resident
|
|
874
|
-
? 'last-known-good'
|
|
875
|
-
: 'failed';
|
|
876
|
-
return {
|
|
877
|
-
readiness,
|
|
878
|
-
samplers,
|
|
879
|
-
textures,
|
|
880
|
-
...(failure === undefined ? {} : { preparationFailure: failure }),
|
|
881
|
-
};
|
|
882
|
-
}
|
|
883
|
-
|
|
884
600
|
export function createRenderSystem(internals: RenderSystemInternals): RenderSystem {
|
|
885
601
|
const phaseCatalogRegistration = internals.profiler?.registerPhaseCatalog(
|
|
886
602
|
'render',
|
|
@@ -896,9 +612,28 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
896
612
|
});
|
|
897
613
|
let preparedFeatureSkylightResources: SkylightBindGroupResources | undefined;
|
|
898
614
|
const dynamicGeometryFrames = createDynamicGeometryFrameBindings();
|
|
615
|
+
let surfaceDynamicInputFrame: SurfaceDynamicInputFrame | undefined;
|
|
899
616
|
let latestCamera: CameraSnapshot | undefined;
|
|
617
|
+
// Last public parameter failure; cleared only after a valid extraction.
|
|
618
|
+
let lastMotionBlurInvalidParams: MotionBlurValidationError | undefined;
|
|
619
|
+
// Lazily install the compute lane when a capable frame demands it.
|
|
620
|
+
let motionBlurFeatureInput: MotionBlurFeatureInput | undefined;
|
|
621
|
+
const motionBlurFeature = createMotionBlurFeature(() => motionBlurFeatureInput);
|
|
622
|
+
const ensureMotionBlurFeature = (): void => {
|
|
623
|
+
const host = internals.featureHost;
|
|
624
|
+
if (
|
|
625
|
+
host === undefined ||
|
|
626
|
+
host.features.some((feature) => feature.identity === 'forgeax.motion-blur')
|
|
627
|
+
) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const installed = host.install(
|
|
631
|
+
motionBlurFeature as import('./features/types').RenderFeature<unknown>,
|
|
632
|
+
);
|
|
633
|
+
if (!installed.ok) internals.errorRegistry.fire(installed.error);
|
|
634
|
+
};
|
|
900
635
|
const pointsLinesOwner = new StandardPointsLinesOwner(internals);
|
|
901
|
-
const instanceCollections = new
|
|
636
|
+
const instanceCollections = new InstanceProjectionStore();
|
|
902
637
|
const reflectionProbeOwner = new ReflectionProbeRecordOwner(internals);
|
|
903
638
|
const ssrFormatReceipts = new WeakMap<
|
|
904
639
|
RhiDevice,
|
|
@@ -926,7 +661,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
926
661
|
const persistentRenderScene = new PersistentRenderScene({
|
|
927
662
|
getDevice: () => internals.device,
|
|
928
663
|
onGpuError: (error) => internals.errorRegistry.fire(error),
|
|
929
|
-
|
|
664
|
+
onRuntimeAssetChange: (worldId, handle) => {
|
|
930
665
|
internals.gpuStore.invalidateMesh(handle, preparedWorlds[worldId] ?? worldId);
|
|
931
666
|
},
|
|
932
667
|
instanceCollections,
|
|
@@ -1074,6 +809,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1074
809
|
),
|
|
1075
810
|
} satisfies import('./pipeline-builder').PipelineBuilderShaderModuleFactory);
|
|
1076
811
|
let gpuDrivenRecoveryCount = 0;
|
|
812
|
+
const surfaceSubmissionObservation = new SurfaceSubmissionObservationOwner(
|
|
813
|
+
() => internals.deviceScope.generation,
|
|
814
|
+
);
|
|
1077
815
|
let gpuDrivenProduction = createGpuDrivenOwner(
|
|
1078
816
|
internals.device,
|
|
1079
817
|
gpuDrivenShaderFactory,
|
|
@@ -1145,6 +883,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1145
883
|
// raw (material-handle-based, cross-world collision semantically correct).
|
|
1146
884
|
const frameState: RenderFrameState = {
|
|
1147
885
|
frameNumber: 0,
|
|
886
|
+
surfaceSubmissionObservation: undefined,
|
|
1148
887
|
reflectionFallbackDemand: false,
|
|
1149
888
|
ssrRequested: false,
|
|
1150
889
|
ssrSpatialAdmission: undefined,
|
|
@@ -1172,6 +911,13 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1172
911
|
depthOfFieldCandidateGraph: null,
|
|
1173
912
|
depthOfFieldAccepted: undefined,
|
|
1174
913
|
depthOfFieldLastSubmitFailed: false,
|
|
914
|
+
barrelDistortionPreviousGraph: null,
|
|
915
|
+
barrelDistortionPreviousGraphKey: null,
|
|
916
|
+
barrelDistortionPreviousPerFrameGraph: undefined,
|
|
917
|
+
barrelDistortionPreviousGraphGeneration: 0,
|
|
918
|
+
barrelDistortionPreviousCompiledGraphGeneration: 0,
|
|
919
|
+
barrelDistortionPreviousStandardLightingGraphSignature: '',
|
|
920
|
+
barrelDistortionCandidateGraph: null,
|
|
1175
921
|
volumetricFogPreviousGraph: null,
|
|
1176
922
|
volumetricFogPreviousGraphKey: null,
|
|
1177
923
|
volumetricFogCandidateGraph: null,
|
|
@@ -1190,6 +936,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1190
936
|
currentFrameObservationSource: undefined,
|
|
1191
937
|
reflectionFallbackObservationSource: undefined,
|
|
1192
938
|
lastSuccessfulCameraAntialias: undefined,
|
|
939
|
+
lastSuccessfulBarrelDistortion: undefined,
|
|
940
|
+
barrelDistortionGraphResolution: 'accepted',
|
|
1193
941
|
temporalGpuState: undefined,
|
|
1194
942
|
autoExposureGpuResources: undefined,
|
|
1195
943
|
pendingAutoExposureGpuResources: undefined,
|
|
@@ -1291,6 +1039,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1291
1039
|
// tiles until the first frame with a castShadow spot (AC-03).
|
|
1292
1040
|
spotShadowSnapshots: [],
|
|
1293
1041
|
};
|
|
1042
|
+
// A feature that is explicitly recoverable on the next frame must not
|
|
1043
|
+
// publish the same transient failure on every render tick. Keep one
|
|
1044
|
+
// renderer-owned cooldown per structured feature failure while retaining
|
|
1045
|
+
// the original error for the first and periodic reports.
|
|
1046
|
+
const pendingFeatureErrorLastReportedFrame = new Map<string, PendingRenderFeatureErrorReport>();
|
|
1294
1047
|
const resolveSsrDependencies = (requested: boolean): SsrDependenciesInspection => {
|
|
1295
1048
|
// Explicit SSR capability preparation belongs to initialization. Inspection
|
|
1296
1049
|
// only projects receipts and never starts work or creates image history.
|
|
@@ -1496,7 +1249,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1496
1249
|
const invalidatePostProcessModule = (id: string): void => {
|
|
1497
1250
|
const entry = lookupPostProcess(id);
|
|
1498
1251
|
if (entry !== undefined) {
|
|
1499
|
-
internals.invalidateShaderModule?.(postProcessShaderModuleLabel(
|
|
1252
|
+
internals.invalidateShaderModule?.(postProcessShaderModuleLabel(entry.source));
|
|
1500
1253
|
}
|
|
1501
1254
|
};
|
|
1502
1255
|
// feat-20260621 M-A2 / w8: expose the eager-created per-id params UBO through
|
|
@@ -1586,6 +1339,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1586
1339
|
if (!destroyed.ok) internals.errorRegistry.fire(destroyed.error);
|
|
1587
1340
|
}
|
|
1588
1341
|
};
|
|
1342
|
+
const disposeActivePostProcessResources = (): void => {
|
|
1343
|
+
const resources = { device: postProcessParamsDevice, paramsBuffers: postProcessParamsBuffers };
|
|
1344
|
+
postProcessParamsBuffers = new Map();
|
|
1345
|
+
disposePostProcessResources(resources);
|
|
1346
|
+
};
|
|
1589
1347
|
const preparePostProcessParamsResources = (
|
|
1590
1348
|
featureEntries: ReadonlyMap<string, PostProcessShaderEntry>,
|
|
1591
1349
|
): Result<PostProcessParamsCandidate, RhiError> => {
|
|
@@ -1752,6 +1510,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1752
1510
|
readonly visible: number;
|
|
1753
1511
|
readonly occluded: number;
|
|
1754
1512
|
readonly lodHistogram: readonly { readonly level: number; readonly count: number }[];
|
|
1513
|
+
readonly submit?: { readonly frameId: number; readonly deviceGeneration: number };
|
|
1755
1514
|
readonly worldSelections?: readonly {
|
|
1756
1515
|
readonly worldKey: number;
|
|
1757
1516
|
readonly primitiveSlot: number;
|
|
@@ -1763,9 +1522,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1763
1522
|
}[];
|
|
1764
1523
|
}
|
|
1765
1524
|
| undefined,
|
|
1525
|
+
targetInspection: LodOcclusionInspection | undefined = lastLodOcclusionInspection,
|
|
1526
|
+
targetWorldAttachments: ReadonlyMap<number, string> = lastLodWorldAttachments,
|
|
1766
1527
|
): void => {
|
|
1767
|
-
if (selection === undefined ||
|
|
1768
|
-
const inspection =
|
|
1528
|
+
if (selection === undefined || targetInspection === undefined) return;
|
|
1529
|
+
const inspection = targetInspection;
|
|
1769
1530
|
// The GPU readback histogram is the selector fact, while final submitted
|
|
1770
1531
|
// counts are owned by the persistent visibility projection. Keeping the
|
|
1771
1532
|
// projection count here excludes ordinary non-LOD geometry (for example a
|
|
@@ -1777,7 +1538,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1777
1538
|
const selectionsByAttachment = new Map<string, (typeof worldSelections)[number][]>();
|
|
1778
1539
|
let attributionValid = true;
|
|
1779
1540
|
for (const selected of worldSelections) {
|
|
1780
|
-
const attachmentId =
|
|
1541
|
+
const attachmentId = targetWorldAttachments.get(selected.worldKey);
|
|
1781
1542
|
if (attachmentId === undefined) {
|
|
1782
1543
|
attributionValid = false;
|
|
1783
1544
|
break;
|
|
@@ -1790,15 +1551,16 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1790
1551
|
const nextWorlds = worlds.map((world) => {
|
|
1791
1552
|
const selected = selectionsByAttachment.get(world.attachmentId);
|
|
1792
1553
|
const baseRow = world.rows[0];
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1554
|
+
// A World with only plain meshes has no LOD selection row. Keep its
|
|
1555
|
+
// projection-only receipt and allow Worlds with valid LOD rows to
|
|
1556
|
+
// retain same-submit attribution. Unknown selected world keys still
|
|
1557
|
+
// fail closed above.
|
|
1558
|
+
if (selected === undefined || baseRow === undefined) return world;
|
|
1559
|
+
// The projection row is intentionally CPU-scoped and may omit
|
|
1560
|
+
// selector-only candidates that remain in the full GPU plan. The
|
|
1561
|
+
// same-submit GPU row owns the denominator; comparing it to the
|
|
1562
|
+
// projection count would reject a valid receipt (for example 11 GPU
|
|
1563
|
+
// candidates versus 10 CPU-admitted renderables).
|
|
1802
1564
|
return Object.freeze({
|
|
1803
1565
|
...world,
|
|
1804
1566
|
attribution: Object.freeze({
|
|
@@ -1828,7 +1590,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1828
1590
|
lastLodOcclusionInspection = inspectLodOcclusion({
|
|
1829
1591
|
...inspection,
|
|
1830
1592
|
count: {
|
|
1831
|
-
...
|
|
1593
|
+
...inspection.count,
|
|
1832
1594
|
candidates: selection.candidateCount,
|
|
1833
1595
|
visible: selection.visible,
|
|
1834
1596
|
occluded: selection.occluded,
|
|
@@ -1861,6 +1623,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1861
1623
|
};
|
|
1862
1624
|
let lastMeshMaterialBindings: readonly MeshMaterialBindingObservation[] = [];
|
|
1863
1625
|
let lastMeshMaterialBindingRenderables: readonly RenderableSnapshot[] | undefined;
|
|
1626
|
+
let lastPresentation: FramePresentation = 'pending';
|
|
1864
1627
|
const createPreparedResolverFactory =
|
|
1865
1628
|
(
|
|
1866
1629
|
runtime: RenderSystemInternals,
|
|
@@ -2024,6 +1787,17 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2024
1787
|
) {
|
|
2025
1788
|
return err(new Error('prepared scene-depth pipeline requires a scene target'));
|
|
2026
1789
|
}
|
|
1790
|
+
// The typed graph composes fullscreen feature bindings from its
|
|
1791
|
+
// current graph views and post-process parameter snapshot at encode
|
|
1792
|
+
// time. Do not manufacture a fallback bind group here: during
|
|
1793
|
+
// registration/recovery its params buffer can still be absent, and
|
|
1794
|
+
// a two-entry fallback cannot satisfy a params-aware layout.
|
|
1795
|
+
if (
|
|
1796
|
+
preparedPipelineIds.has(pipeline as object) &&
|
|
1797
|
+
descriptor.values.fullscreen === true
|
|
1798
|
+
) {
|
|
1799
|
+
return ok(undefined);
|
|
1800
|
+
}
|
|
2027
1801
|
if (preparedGroup0Pipelines.has(pipeline as object)) {
|
|
2028
1802
|
const layout =
|
|
2029
1803
|
(materialShaderId === undefined
|
|
@@ -2161,10 +1935,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2161
1935
|
createPreparedResolverCaches,
|
|
2162
1936
|
});
|
|
2163
1937
|
return {
|
|
2164
|
-
|
|
1938
|
+
setSurfaceDynamicInput(frame: SurfaceDynamicInputFrame | undefined): void {
|
|
1939
|
+
surfaceDynamicInputFrame = frame;
|
|
1940
|
+
},
|
|
2165
1941
|
initializeSsr: ensureSsrFormatProbe,
|
|
2166
1942
|
get instanceCollectionsInspection(): readonly InstanceCollectionInspection[] {
|
|
2167
|
-
return instanceCollections._inspections();
|
|
1943
|
+
return instanceCollections._inspections(frameState.frameNumber - 1);
|
|
2168
1944
|
},
|
|
2169
1945
|
releaseProfilerCatalog(): void {
|
|
2170
1946
|
releaseProfilerCatalog?.();
|
|
@@ -2177,9 +1953,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2177
1953
|
return persistentRenderScene.bounds(world, entity);
|
|
2178
1954
|
},
|
|
2179
1955
|
get renderScene(): RenderSceneInspection {
|
|
1956
|
+
const submission = surfaceSubmissionObservation.inspect();
|
|
2180
1957
|
return {
|
|
2181
1958
|
...persistentRenderScene.inspect(),
|
|
2182
1959
|
gpuDriven: gpuDrivenProduction.inspect(),
|
|
1960
|
+
...(submission === undefined ? {} : { submission }),
|
|
2183
1961
|
};
|
|
2184
1962
|
},
|
|
2185
1963
|
get gpuDrivenInspection(): GpuDrivenProductionInspection {
|
|
@@ -2234,6 +2012,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2234
2012
|
get reflectionFallbackCompletion(): Promise<void> | undefined {
|
|
2235
2013
|
return frameState.reflectionFallbackCompletion;
|
|
2236
2014
|
},
|
|
2015
|
+
get presentation(): FramePresentation {
|
|
2016
|
+
return lastPresentation;
|
|
2017
|
+
},
|
|
2237
2018
|
isCubeCapturePending(target: RenderTarget): boolean {
|
|
2238
2019
|
return cubeCaptureScheduler.inspect(target).candidateGeneration !== undefined;
|
|
2239
2020
|
},
|
|
@@ -2274,24 +2055,20 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2274
2055
|
});
|
|
2275
2056
|
},
|
|
2276
2057
|
get motionBlurInspection(): MotionBlurInspection | undefined {
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
frameState.
|
|
2283
|
-
frameState.
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
passName: 'motion-blur',
|
|
2292
|
-
historyWrites: 0,
|
|
2293
|
-
...(unavailable ? { lastFailure: 'scene-data-unavailable' as const } : {}),
|
|
2294
|
-
};
|
|
2058
|
+
return projectMotionBlurInspection({
|
|
2059
|
+
camera: latestCamera,
|
|
2060
|
+
invalidParams: lastMotionBlurInvalidParams,
|
|
2061
|
+
capabilities: internals.device.caps,
|
|
2062
|
+
acceptedTemporal: frameState.lastSuccessfulTemporalView,
|
|
2063
|
+
transaction: frameState.temporalFrameTransaction.inspect(),
|
|
2064
|
+
execution: frameState.motionBlurExecution,
|
|
2065
|
+
temporalFrameId: frameState.temporalFrame?.frameId,
|
|
2066
|
+
deviceGeneration: internals.deviceScope.generation,
|
|
2067
|
+
graphGeneration: frameState.graphGeneration,
|
|
2068
|
+
});
|
|
2069
|
+
},
|
|
2070
|
+
get motionBlurInvalidParams(): MotionBlurValidationError | undefined {
|
|
2071
|
+
return lastMotionBlurInvalidParams;
|
|
2295
2072
|
},
|
|
2296
2073
|
get depthOfFieldInspection(): DepthOfFieldInspection | undefined {
|
|
2297
2074
|
const camera = latestCamera;
|
|
@@ -2354,22 +2131,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2354
2131
|
const lifecycle = resources?.inspectBloomResources?.(
|
|
2355
2132
|
frameState.compiledFrameGraph?.inspect(),
|
|
2356
2133
|
);
|
|
2357
|
-
return Object.freeze(
|
|
2358
|
-
lifecycle ?? {
|
|
2359
|
-
graphStatus: 'empty',
|
|
2360
|
-
enabled: false,
|
|
2361
|
-
targetCount: 0,
|
|
2362
|
-
targetBytes: 0,
|
|
2363
|
-
resourceCount: 0,
|
|
2364
|
-
passCount: 0,
|
|
2365
|
-
encodeCount: 0,
|
|
2366
|
-
bindGroupCount: 0,
|
|
2367
|
-
uploadCount: 0,
|
|
2368
|
-
residentChildBytes: 0,
|
|
2369
|
-
generation: 0,
|
|
2370
|
-
state: 'off',
|
|
2371
|
-
},
|
|
2372
|
-
);
|
|
2134
|
+
return Object.freeze(lifecycle ?? emptyBloomInspection());
|
|
2373
2135
|
},
|
|
2374
2136
|
get transmission(): TransmissionInspection | undefined {
|
|
2375
2137
|
return lastTransmissionInspection;
|
|
@@ -2444,6 +2206,14 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2444
2206
|
const profileSession = internals.profiler?.activeSession();
|
|
2445
2207
|
let ownsProfileFrame = false;
|
|
2446
2208
|
let submitted = false;
|
|
2209
|
+
// A failed draw cannot publish a startup completion fact. Reset the
|
|
2210
|
+
// projection before extraction so a later receipt never reuses an old
|
|
2211
|
+
// scene's readiness.
|
|
2212
|
+
lastPresentation = 'pending';
|
|
2213
|
+
// A prior failed record/submit may have staged a temporal capture. A
|
|
2214
|
+
// capture belongs only to the draw call that created it; discard it
|
|
2215
|
+
// before this call can prepare or commit a new candidate.
|
|
2216
|
+
persistentRenderScene.discardTemporalFrame();
|
|
2447
2217
|
// A failed draw must never leave a previous frame eligible to publish a
|
|
2448
2218
|
// newly accepted dynamic-geometry candidate.
|
|
2449
2219
|
dynamicGeometryFrames.begin();
|
|
@@ -2475,55 +2245,67 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2475
2245
|
dispatchCounts.unlit = 0;
|
|
2476
2246
|
|
|
2477
2247
|
const resourceWorld = compositionWorlds[resourceOwner] as World;
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
:
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2248
|
+
let frame: ReturnType<PersistentRenderScene['extractComposition']>;
|
|
2249
|
+
try {
|
|
2250
|
+
frame = runProfiledRenderPhase(profileSession, 'extract', () => {
|
|
2251
|
+
return persistentRenderScene.extractComposition(
|
|
2252
|
+
compositionWorlds,
|
|
2253
|
+
{ cameraOwner, resourceOwner },
|
|
2254
|
+
internals.assets.catalogEpoch,
|
|
2255
|
+
(renderables) =>
|
|
2256
|
+
extractFrames(
|
|
2257
|
+
compositionWorlds,
|
|
2258
|
+
{
|
|
2259
|
+
cameraOwner,
|
|
2260
|
+
resourceOwner,
|
|
2261
|
+
...(cameraEntityKey === undefined ? {} : { cameraEntityKey }),
|
|
2262
|
+
},
|
|
2263
|
+
internals.assets,
|
|
2264
|
+
internals.getPipelineState(),
|
|
2265
|
+
persistentRenderScene.materialSnapshotCacheStore(),
|
|
2266
|
+
{
|
|
2267
|
+
...(internals.device.caps.backendKind === 'null'
|
|
2268
|
+
? {}
|
|
2269
|
+
: {
|
|
2270
|
+
materialContext: {
|
|
2271
|
+
backend:
|
|
2272
|
+
internals.device.caps.backendKind === 'wgpu-webgl2'
|
|
2273
|
+
? ('webgl2' as const)
|
|
2274
|
+
: internals.device.caps.backendKind,
|
|
2275
|
+
capability: internals.device.caps.storageBuffer
|
|
2276
|
+
? ('storage-buffer' as const)
|
|
2277
|
+
: ('uniform-fallback' as const),
|
|
2278
|
+
pipeline: 'forward' as const,
|
|
2279
|
+
geometry: 'mesh' as const,
|
|
2280
|
+
pass: 'forward' as const,
|
|
2281
|
+
profile: 'forgeax-material-wgsl-v1' as const,
|
|
2282
|
+
toolchain: 'naga-oil' as const,
|
|
2283
|
+
instrumentation: 'none' as const,
|
|
2284
|
+
},
|
|
2285
|
+
}),
|
|
2286
|
+
cull: 'none',
|
|
2287
|
+
retainHidden: true,
|
|
2288
|
+
renderables,
|
|
2289
|
+
instanceCollections,
|
|
2290
|
+
...(!internals.device.caps.storageBuffer ||
|
|
2291
|
+
internals.getMaterialShaderArtifact === undefined
|
|
2292
|
+
? {}
|
|
2293
|
+
: { getMaterialShaderArtifact: internals.getMaterialShaderArtifact }),
|
|
2294
|
+
},
|
|
2295
|
+
),
|
|
2296
|
+
compositionLeases,
|
|
2297
|
+
);
|
|
2298
|
+
});
|
|
2299
|
+
} catch (cause) {
|
|
2300
|
+
if (cause instanceof MotionBlurValidationError) {
|
|
2301
|
+
lastMotionBlurInvalidParams = cause;
|
|
2302
|
+
latestCamera = undefined;
|
|
2303
|
+
internals.errorRegistry.fire(cause);
|
|
2304
|
+
return false;
|
|
2305
|
+
}
|
|
2306
|
+
throw cause;
|
|
2307
|
+
}
|
|
2308
|
+
lastMotionBlurInvalidParams = undefined;
|
|
2527
2309
|
const {
|
|
2528
2310
|
cameras: extractedCameras,
|
|
2529
2311
|
cubeCameras,
|
|
@@ -2531,6 +2313,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2531
2313
|
environment,
|
|
2532
2314
|
environmentReady,
|
|
2533
2315
|
volumetricFog,
|
|
2316
|
+
cloudLayer,
|
|
2534
2317
|
renderables,
|
|
2535
2318
|
dispatch,
|
|
2536
2319
|
shadowCasterEntityKeys: extractedShadowCasterEntityKeys,
|
|
@@ -2759,7 +2542,27 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2759
2542
|
);
|
|
2760
2543
|
const submissionRenderables = visibilityProjection.renderables;
|
|
2761
2544
|
const submissionDispatch = visibilityProjection.dispatch;
|
|
2545
|
+
const presentationProjection = projectFramePresentation({
|
|
2546
|
+
hasCamera: cameras.length > 0,
|
|
2547
|
+
environmentReady,
|
|
2548
|
+
hasEnvironment: environment !== undefined,
|
|
2549
|
+
submissionRenderables,
|
|
2550
|
+
submissionDispatch,
|
|
2551
|
+
preparedWorlds,
|
|
2552
|
+
internals,
|
|
2553
|
+
});
|
|
2554
|
+
const presentationRenderables = presentationProjection.renderables;
|
|
2555
|
+
let framePresentation = presentationProjection.presentation;
|
|
2762
2556
|
const inspectionCamera = latestCamera;
|
|
2557
|
+
// The public frame receipt is allocated by WebGPURenderer immediately
|
|
2558
|
+
// before this draw (`observationFrameId`). RenderSystem's private
|
|
2559
|
+
// frameNumber is an internal generation and also advances on failed
|
|
2560
|
+
// record attempts, so it cannot be used as receipt identity. Keep the
|
|
2561
|
+
// internal generation for recovery/visibility state, but bind the LOD
|
|
2562
|
+
// inspection to the frame id that the caller will receive.
|
|
2563
|
+
const lodSubmitFrameId =
|
|
2564
|
+
(internals as RenderSystemInternals & { readonly observationFrameId?: number })
|
|
2565
|
+
.observationFrameId ?? frameState.frameNumber;
|
|
2763
2566
|
let lodCandidateCountForFrame = 0;
|
|
2764
2567
|
if (inspectionCamera !== undefined) {
|
|
2765
2568
|
const firstRenderable = renderables[0];
|
|
@@ -2802,7 +2605,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2802
2605
|
renderables,
|
|
2803
2606
|
submissionRenderables,
|
|
2804
2607
|
inspectionCamera,
|
|
2805
|
-
|
|
2608
|
+
lodSubmitFrameId,
|
|
2806
2609
|
worldKeys,
|
|
2807
2610
|
slotByEntity,
|
|
2808
2611
|
{
|
|
@@ -2834,7 +2637,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2834
2637
|
firstRenderable === undefined
|
|
2835
2638
|
? 'none'
|
|
2836
2639
|
: `asset-handle:${firstRenderable.assetHandle}`,
|
|
2837
|
-
sourceKey: `render-frame:${
|
|
2640
|
+
sourceKey: `render-frame:${lodSubmitFrameId}`,
|
|
2838
2641
|
},
|
|
2839
2642
|
view: {
|
|
2840
2643
|
attachmentId:
|
|
@@ -2847,7 +2650,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2847
2650
|
primitiveSlot: 0,
|
|
2848
2651
|
slotGeneration: persistentRenderScene.inspect().topology.revision,
|
|
2849
2652
|
},
|
|
2850
|
-
generation:
|
|
2653
|
+
generation: lodSubmitFrameId,
|
|
2851
2654
|
count: {
|
|
2852
2655
|
candidates: candidateCount,
|
|
2853
2656
|
visible: inspectionRenderables.length,
|
|
@@ -2866,7 +2669,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2866
2669
|
visible: true,
|
|
2867
2670
|
})),
|
|
2868
2671
|
submit: {
|
|
2869
|
-
frameId:
|
|
2672
|
+
frameId: lodSubmitFrameId,
|
|
2870
2673
|
build: resolveInspectionBuild(internals),
|
|
2871
2674
|
deviceGeneration: internals.deviceScope.generation,
|
|
2872
2675
|
},
|
|
@@ -2878,7 +2681,14 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2878
2681
|
lastLodWorldAttachments = new Map();
|
|
2879
2682
|
}
|
|
2880
2683
|
const temporalDemanded =
|
|
2881
|
-
cameras[0]?.antialias === 'taa' ||
|
|
2684
|
+
cameras[0]?.antialias === 'taa' ||
|
|
2685
|
+
(cameras[0]?.motionBlur !== undefined &&
|
|
2686
|
+
motionBlurTemporalDemand({
|
|
2687
|
+
shutterAngle: cameras[0].motionBlur.shutterAngle,
|
|
2688
|
+
maxRadiusPixels: cameras[0].motionBlur.maxRadiusPixels,
|
|
2689
|
+
sampleCount: cameras[0].motionBlur.sampleCount,
|
|
2690
|
+
targetFps: cameras[0].motionBlur.targetFps ?? 60,
|
|
2691
|
+
}));
|
|
2882
2692
|
if (temporalDemanded) {
|
|
2883
2693
|
persistentRenderScene.prepareTemporalFrame(submissionRenderables);
|
|
2884
2694
|
}
|
|
@@ -2938,6 +2748,17 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2938
2748
|
bindGroupCounts.createBindGroup = 0;
|
|
2939
2749
|
bindGroupCounts.keys = [];
|
|
2940
2750
|
const preparedPipelineState = internals.getPipelineState();
|
|
2751
|
+
const featureView = createCloudFeatureView(
|
|
2752
|
+
cameras[0],
|
|
2753
|
+
compositionWorlds,
|
|
2754
|
+
cameraOwner,
|
|
2755
|
+
internals.canvas.width,
|
|
2756
|
+
internals.canvas.height,
|
|
2757
|
+
internals.deviceScope.generation,
|
|
2758
|
+
frameState.lastSuccessfulTemporalView === undefined,
|
|
2759
|
+
lastSubmittedGeneration !== undefined &&
|
|
2760
|
+
lastSubmittedGeneration !== internals.deviceScope.generation,
|
|
2761
|
+
);
|
|
2941
2762
|
const bindGroupSkipReason: RenderPhaseSkipReason | undefined =
|
|
2942
2763
|
internals.featureHost === undefined
|
|
2943
2764
|
? 'feature-host-unavailable'
|
|
@@ -2988,7 +2809,46 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2988
2809
|
colorAttachmentFormat: preparedPipelineState.colorAttachmentFormat,
|
|
2989
2810
|
storageBuffer: internals.device.caps.storageBuffer,
|
|
2990
2811
|
multisample: internals.device.caps.backendKind !== 'wgpu-webgl2',
|
|
2812
|
+
cloudHistory: cloudLayer !== undefined,
|
|
2991
2813
|
});
|
|
2814
|
+
const motionBlurParams = cameras[0]?.motionBlur;
|
|
2815
|
+
let motionBlurDelta = 0;
|
|
2816
|
+
try {
|
|
2817
|
+
const delta = (compositionWorlds[cameraOwner] as World).getResource(Time).delta;
|
|
2818
|
+
motionBlurDelta = Number.isFinite(delta) ? Math.max(0, delta) : 0;
|
|
2819
|
+
} catch {
|
|
2820
|
+
motionBlurDelta = 0;
|
|
2821
|
+
}
|
|
2822
|
+
const acceptedSampleTime = frameState.lastSuccessfulTemporalView?.sampleTimeSeconds;
|
|
2823
|
+
const cameraViewIdentity = `camera:${cameras[0]?.entityKey ?? 0}`;
|
|
2824
|
+
const canvasWidth = Math.max(1, internals.canvas.width);
|
|
2825
|
+
const canvasHeight = Math.max(1, internals.canvas.height);
|
|
2826
|
+
const motionBlurPlan = planMotionBlurFrame({
|
|
2827
|
+
params: motionBlurParams,
|
|
2828
|
+
sampleTimeSeconds: opts.sampleTimeSeconds,
|
|
2829
|
+
acceptedSampleTimeSeconds: acceptedSampleTime,
|
|
2830
|
+
fallbackDeltaSeconds: motionBlurDelta,
|
|
2831
|
+
acceptedTemporal: frameState.lastSuccessfulTemporalView,
|
|
2832
|
+
temporalReset: opts.temporalReset === true,
|
|
2833
|
+
width: canvasWidth,
|
|
2834
|
+
height: canvasHeight,
|
|
2835
|
+
cameraViewIdentity,
|
|
2836
|
+
historyVersion: cameras[0]?.historyVersion ?? 0,
|
|
2837
|
+
environmentSignature: environment?.environmentSignature ?? '',
|
|
2838
|
+
fogSignature: environment?.fogSignature ?? '',
|
|
2839
|
+
deviceGeneration: internals.deviceScope?.generation ?? 0,
|
|
2840
|
+
});
|
|
2841
|
+
const demandedMotionBlur = motionBlurPlan.demanded;
|
|
2842
|
+
motionBlurFeatureInput = motionBlurPlan.featureInput;
|
|
2843
|
+
if (
|
|
2844
|
+
demandedMotionBlur &&
|
|
2845
|
+
internals.device.caps.compute === true &&
|
|
2846
|
+
internals.device.caps.storageBuffer === true &&
|
|
2847
|
+
internals.device.caps.storageTexture === true &&
|
|
2848
|
+
internals.device.caps.rgba16floatRenderable === true
|
|
2849
|
+
) {
|
|
2850
|
+
ensureMotionBlurFeature();
|
|
2851
|
+
}
|
|
2992
2852
|
preparedFeatureSkylightResources =
|
|
2993
2853
|
preparedPipelineState === null
|
|
2994
2854
|
? undefined
|
|
@@ -3001,11 +2861,14 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3001
2861
|
worlds: compositionWorlds,
|
|
3002
2862
|
owner: resourceOwner,
|
|
3003
2863
|
frameNumber: frameState.frameNumber,
|
|
2864
|
+
...(cameras[0] === undefined ? {} : { selectedCamera: cameras[0] }),
|
|
2865
|
+
frameSize: { width: internals.canvas.width, height: internals.canvas.height },
|
|
3004
2866
|
visibilitySnapshots: frame.featureVisibilitySnapshots,
|
|
3005
2867
|
hiddenEntityReports: frame.hiddenEntityReports,
|
|
3006
2868
|
targets: featureTargets,
|
|
3007
2869
|
generation: internals.featureHost?.preparedGeneration ?? 0,
|
|
3008
2870
|
caps: internals.device.caps,
|
|
2871
|
+
frame: createCloudFeatureFrameContext(cloudLayer, featureView),
|
|
3009
2872
|
...(internals.getMaterialShaderBindingContract === undefined
|
|
3010
2873
|
? {}
|
|
3011
2874
|
: { materialShaderBindingContract: internals.getMaterialShaderBindingContract }),
|
|
@@ -3035,11 +2898,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3035
2898
|
gpuWork: featureGpuWork,
|
|
3036
2899
|
});
|
|
3037
2900
|
lastVisibilityStats.explicitlyHidden = featureFrame.hiddenEntityReports.length;
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
2901
|
+
reportPendingRenderFeatureErrors(
|
|
2902
|
+
featureFrame.errors,
|
|
2903
|
+
frameState.frameNumber,
|
|
2904
|
+
pendingFeatureErrorLastReportedFrame,
|
|
2905
|
+
internals.errorRegistry,
|
|
2906
|
+
);
|
|
3043
2907
|
const postProcessParamsCandidate = preparePostProcessParamsResources(
|
|
3044
2908
|
featureFrame.fullscreenEffects,
|
|
3045
2909
|
);
|
|
@@ -3054,6 +2918,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3054
2918
|
featureGraphCandidate = {
|
|
3055
2919
|
plans: featureFrame.plans,
|
|
3056
2920
|
fullscreenEffects: featureFrame.fullscreenEffects,
|
|
2921
|
+
postProcessIdentities: featureFrame.postProcessIdentities,
|
|
3057
2922
|
...(featureFrame.requiresPreparedResourceKey
|
|
3058
2923
|
? { preparedResourceKey: `frame-${frameState.frameNumber}` }
|
|
3059
2924
|
: {}),
|
|
@@ -3172,7 +3037,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3172
3037
|
}
|
|
3173
3038
|
return runProfiledRenderPhase(profileSession, phase, action);
|
|
3174
3039
|
};
|
|
3175
|
-
|
|
3040
|
+
const bloomAdmitted = standardBloomAdmitted(cameras[0]);
|
|
3041
|
+
if (bloomAdmitted) {
|
|
3176
3042
|
internals.getPipelineState()?.perPassResources.ensureBloomResources?.();
|
|
3177
3043
|
}
|
|
3178
3044
|
const liveOutput = cameras[0]?.output;
|
|
@@ -3194,11 +3060,44 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3194
3060
|
Number.isFinite(deltaTime) ? Math.max(0, deltaTime) : 0,
|
|
3195
3061
|
);
|
|
3196
3062
|
}
|
|
3063
|
+
const surfaceSubmissionCandidate = surfaceSubmissionObservation.begin({
|
|
3064
|
+
frameId:
|
|
3065
|
+
(internals as RenderSystemInternals & { readonly observationFrameId?: number })
|
|
3066
|
+
.observationFrameId ?? frameState.frameNumber,
|
|
3067
|
+
requestedLane: opts.geometryLane === 'direct' ? 'direct' : 'gpu-driven',
|
|
3068
|
+
deviceGeneration: internals.deviceScope.generation,
|
|
3069
|
+
resourceGeneration: gpuDrivenProduction.inspect().resourceGeneration,
|
|
3070
|
+
});
|
|
3071
|
+
frameState.surfaceSubmissionObservation = surfaceSubmissionCandidate;
|
|
3197
3072
|
const probeCaptureScene =
|
|
3198
3073
|
shadowCasterProjection !== undefined &&
|
|
3199
3074
|
reflectionProbeRecord.graph.work.some((work) => work.rawCaptureFace !== undefined)
|
|
3200
3075
|
? projectCaptureScene(shadowCasterProjection, submissionRenderables, orderedDispatch)
|
|
3201
3076
|
: undefined;
|
|
3077
|
+
// This is a transient projection of the record owner's actual visible
|
|
3078
|
+
// draws. It lets the presentation fact distinguish a clear/submit
|
|
3079
|
+
// from a frame where geometry or its pipeline was skipped, without
|
|
3080
|
+
// retaining a second readiness registry or per-asset counter.
|
|
3081
|
+
const presentedRenderableKeys = new Set<number>();
|
|
3082
|
+
const presentedSubmeshKeys = new Set<string>();
|
|
3083
|
+
const consumeDynamicGeometry = dynamicGeometryFrames.onRenderableDraw(compositionWorlds);
|
|
3084
|
+
const markPresentedRenderable = (
|
|
3085
|
+
entry: Parameters<typeof consumeDynamicGeometry>[0],
|
|
3086
|
+
submeshIndex?: number,
|
|
3087
|
+
receipt?: RenderableDrawReceipt,
|
|
3088
|
+
): void => {
|
|
3089
|
+
const entityKey = worldEntityKey(
|
|
3090
|
+
worldKeys[entry.source.worldId] ?? entry.source.worldId,
|
|
3091
|
+
entry.source.entityKey,
|
|
3092
|
+
);
|
|
3093
|
+
if (receipt?.ready !== false) {
|
|
3094
|
+
presentedRenderableKeys.add(entityKey);
|
|
3095
|
+
}
|
|
3096
|
+
if (submeshIndex !== undefined && receipt?.ready !== false) {
|
|
3097
|
+
presentedSubmeshKeys.add(`${entityKey}:${submeshIndex}`);
|
|
3098
|
+
}
|
|
3099
|
+
consumeDynamicGeometry(entry, receipt?.lane ?? 'cpu');
|
|
3100
|
+
};
|
|
3202
3101
|
submitted = runProfiledRenderPhase(profileSession, 'record', () =>
|
|
3203
3102
|
recordFrame(
|
|
3204
3103
|
internals,
|
|
@@ -3226,7 +3125,20 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3226
3125
|
activeEntityKeys: visibilityProjection.activeEntityKeys,
|
|
3227
3126
|
activeEntityRevision: visibilityProjection.activeEntityRevision,
|
|
3228
3127
|
telemetryCandidateCount: lodCandidateCountForFrame,
|
|
3128
|
+
telemetrySubmit: {
|
|
3129
|
+
frameId: lodSubmitFrameId,
|
|
3130
|
+
deviceGeneration: internals.deviceScope.generation,
|
|
3131
|
+
},
|
|
3229
3132
|
...(occlusionProjection === undefined ? {} : { occlusion: occlusionProjection }),
|
|
3133
|
+
frameTime: (() => {
|
|
3134
|
+
const elapsed = (compositionWorlds[cameraOwner] as World).getResource(Time).elapsed;
|
|
3135
|
+
return Number.isFinite(elapsed) ? elapsed : 0;
|
|
3136
|
+
})(),
|
|
3137
|
+
deviceGeneration: internals.deviceScope.generation,
|
|
3138
|
+
...(surfaceDynamicInputFrame === undefined
|
|
3139
|
+
? {}
|
|
3140
|
+
: { surfaceDynamicInput: surfaceDynamicInputFrame }),
|
|
3141
|
+
...(opts.geometryLane === undefined ? {} : { geometryLane: opts.geometryLane }),
|
|
3230
3142
|
},
|
|
3231
3143
|
compositionLeases,
|
|
3232
3144
|
featureGraphCandidate,
|
|
@@ -3253,10 +3165,16 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3253
3165
|
worldKeys,
|
|
3254
3166
|
undefined,
|
|
3255
3167
|
ssrDependencies,
|
|
3256
|
-
|
|
3168
|
+
markPresentedRenderable,
|
|
3169
|
+
environment?.fog,
|
|
3170
|
+
opts.sampleTimeSeconds,
|
|
3171
|
+
opts.temporalReset === true,
|
|
3172
|
+
frame.cloudLayer,
|
|
3257
3173
|
),
|
|
3258
3174
|
);
|
|
3259
3175
|
dynamicGeometryFrames.commit(submitted);
|
|
3176
|
+
if (!submitted) surfaceSubmissionCandidate.abort();
|
|
3177
|
+
frameState.surfaceSubmissionObservation = undefined;
|
|
3260
3178
|
if (!submitted) discardLiveFeatureState();
|
|
3261
3179
|
if (submitted && lastLodOcclusionInspection !== undefined) {
|
|
3262
3180
|
const query = ensureOcclusionRuntime().inspect();
|
|
@@ -3280,6 +3198,111 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3280
3198
|
(frameState.currentDirectionalShadowView !== null &&
|
|
3281
3199
|
(lights.lightViewProj?.length ?? 0) > 0 &&
|
|
3282
3200
|
(internals.getPipelineState()?.perPassResources.shadowMapSize ?? 0) > 0);
|
|
3201
|
+
|
|
3202
|
+
// A successful queue submit is necessary but not sufficient for the
|
|
3203
|
+
// startup presentation fact. Reuse the same visible snapshots and
|
|
3204
|
+
// producer-owned GPU stores consumed by record so missing geometry,
|
|
3205
|
+
// material bindings, dynamic video frames, or requested shadow work
|
|
3206
|
+
// cannot dismiss the loading screen behind a clear/fallback pass.
|
|
3207
|
+
if (submitted && framePresentation === 'ready' && cameras.length > 0) {
|
|
3208
|
+
const pipelineState = internals.getPipelineState();
|
|
3209
|
+
const visibleRenderableKeys = new Set(
|
|
3210
|
+
presentationRenderables.map((renderable) =>
|
|
3211
|
+
worldEntityKey(
|
|
3212
|
+
worldKeys[renderable.worldId] ?? renderable.worldId,
|
|
3213
|
+
renderable.entityKey,
|
|
3214
|
+
),
|
|
3215
|
+
),
|
|
3216
|
+
);
|
|
3217
|
+
if (
|
|
3218
|
+
pipelineState === null ||
|
|
3219
|
+
frameState.compiledFrameGraph === null ||
|
|
3220
|
+
[...visibleRenderableKeys].some((key) => !presentedRenderableKeys.has(key))
|
|
3221
|
+
) {
|
|
3222
|
+
framePresentation = 'pending';
|
|
3223
|
+
}
|
|
3224
|
+
for (const renderable of presentationRenderables) {
|
|
3225
|
+
if (framePresentation === 'pending') break;
|
|
3226
|
+
const renderableWorld = preparedWorlds[renderable.worldId];
|
|
3227
|
+
const meshHandles =
|
|
3228
|
+
renderableWorld === undefined
|
|
3229
|
+
? undefined
|
|
3230
|
+
: (internals.gpuStore.getMeshGpuHandles(
|
|
3231
|
+
toShared<'MeshAsset'>(renderable.assetHandle),
|
|
3232
|
+
renderableWorld,
|
|
3233
|
+
) ?? pipelineState?.meshes.get(renderable.assetHandle));
|
|
3234
|
+
if (meshHandles === undefined) {
|
|
3235
|
+
framePresentation = 'pending';
|
|
3236
|
+
break;
|
|
3237
|
+
}
|
|
3238
|
+
const entityKey = worldEntityKey(
|
|
3239
|
+
worldKeys[renderable.worldId] ?? renderable.worldId,
|
|
3240
|
+
renderable.entityKey,
|
|
3241
|
+
);
|
|
3242
|
+
const gpuClaimedSubmeshes = new Set<number>();
|
|
3243
|
+
for (const [compactIndex, draw] of (renderable.gpuDrivenDraws ?? []).entries()) {
|
|
3244
|
+
const submeshIndex = draw.drawItemIndex ?? compactIndex;
|
|
3245
|
+
if (presentedSubmeshKeys.has(`${entityKey}:${submeshIndex}`)) {
|
|
3246
|
+
gpuClaimedSubmeshes.add(submeshIndex);
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
if (renderable.pointsLines === undefined) {
|
|
3250
|
+
for (const [submeshIndex] of meshHandles.submeshes.entries()) {
|
|
3251
|
+
if (gpuClaimedSubmeshes.has(submeshIndex)) continue;
|
|
3252
|
+
if (!presentedSubmeshKeys.has(`${entityKey}:${submeshIndex}`)) {
|
|
3253
|
+
framePresentation = 'pending';
|
|
3254
|
+
break;
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
if (framePresentation === 'pending') break;
|
|
3259
|
+
for (const material of renderable.materials) {
|
|
3260
|
+
const residency = observeMaterialResidency(renderableWorld, material, internals);
|
|
3261
|
+
if (residency.readiness === 'pending' || residency.readiness === 'failed') {
|
|
3262
|
+
framePresentation = 'pending';
|
|
3263
|
+
break;
|
|
3264
|
+
}
|
|
3265
|
+
for (const clip of material.videoTextureFields?.values() ?? []) {
|
|
3266
|
+
if (internals.dynamicTextureStore?.getView(clip) === undefined) {
|
|
3267
|
+
framePresentation = 'pending';
|
|
3268
|
+
break;
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
if (framePresentation === 'pending') break;
|
|
3272
|
+
}
|
|
3273
|
+
if (framePresentation === 'pending') break;
|
|
3274
|
+
}
|
|
3275
|
+
if (
|
|
3276
|
+
framePresentation === 'ready' &&
|
|
3277
|
+
directionalQuality !== undefined &&
|
|
3278
|
+
(!directionalShadowReady ||
|
|
3279
|
+
(shadowCasterDrawKeys.size > 0 &&
|
|
3280
|
+
!frameState.directionalShadowCacheRecorded &&
|
|
3281
|
+
frameState.directionalShadowCache === null))
|
|
3282
|
+
) {
|
|
3283
|
+
framePresentation = 'pending';
|
|
3284
|
+
}
|
|
3285
|
+
if (
|
|
3286
|
+
framePresentation === 'ready' &&
|
|
3287
|
+
lights.pointShadow.some(
|
|
3288
|
+
(shadow) =>
|
|
3289
|
+
shadow.shadowAtlasLayer >= 0 &&
|
|
3290
|
+
(shadow.shadowMatrices.length < 96 ||
|
|
3291
|
+
[...shadow.shadowMatrices].some((value) => !Number.isFinite(value))),
|
|
3292
|
+
)
|
|
3293
|
+
) {
|
|
3294
|
+
framePresentation = 'pending';
|
|
3295
|
+
}
|
|
3296
|
+
if (
|
|
3297
|
+
framePresentation === 'ready' &&
|
|
3298
|
+
lights.spot.some(
|
|
3299
|
+
(spot) =>
|
|
3300
|
+
spot.castShadow && (spot.lightViewProj === undefined || spot.shadowAtlasTile < 0),
|
|
3301
|
+
)
|
|
3302
|
+
) {
|
|
3303
|
+
framePresentation = 'pending';
|
|
3304
|
+
}
|
|
3305
|
+
}
|
|
3283
3306
|
if (submitted && directionalShadowReady) {
|
|
3284
3307
|
lastDirectionalShadowCandidate = 'accepted';
|
|
3285
3308
|
} else if (directionalQuality !== undefined) {
|
|
@@ -3297,6 +3320,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3297
3320
|
};
|
|
3298
3321
|
}
|
|
3299
3322
|
if (submitted) {
|
|
3323
|
+
lastPresentation = framePresentation;
|
|
3300
3324
|
recoveryOwner.setLastSuccessfulFrameSeed({
|
|
3301
3325
|
frame,
|
|
3302
3326
|
worlds: compositionWorlds,
|
|
@@ -3304,6 +3328,19 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3304
3328
|
resourceOwner: composition.owners.resourceOwner,
|
|
3305
3329
|
width: Math.max(1, internals.canvas.width),
|
|
3306
3330
|
height: Math.max(1, internals.canvas.height),
|
|
3331
|
+
frameTime: (() => {
|
|
3332
|
+
const elapsed = (compositionWorlds[cameraOwner] as World).getResource(Time).elapsed;
|
|
3333
|
+
return Number.isFinite(elapsed) ? elapsed : 0;
|
|
3334
|
+
})(),
|
|
3335
|
+
...(surfaceDynamicInputFrame === undefined
|
|
3336
|
+
? {}
|
|
3337
|
+
: { surfaceDynamicInput: surfaceDynamicInputFrame }),
|
|
3338
|
+
...(frameState.recoveryMaterialArtifacts === undefined
|
|
3339
|
+
? {}
|
|
3340
|
+
: { materialArtifacts: frameState.recoveryMaterialArtifacts }),
|
|
3341
|
+
...(frameState.recoveryShadowMaterialArtifacts === undefined
|
|
3342
|
+
? {}
|
|
3343
|
+
: { shadowMaterialArtifacts: frameState.recoveryShadowMaterialArtifacts }),
|
|
3307
3344
|
});
|
|
3308
3345
|
submittedFrameCount += 1;
|
|
3309
3346
|
lastSubmittedGeneration = internals.deviceScope?.generation;
|
|
@@ -3317,13 +3354,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3317
3354
|
internals.errorRegistry.fire(temporalCommit.error);
|
|
3318
3355
|
}
|
|
3319
3356
|
frameState.lastSuccessfulCameraAntialias = cameras[0]?.antialias;
|
|
3320
|
-
const submittedCamera = cameras[0];
|
|
3321
3357
|
const submittedDepthOfField =
|
|
3322
|
-
|
|
3358
|
+
cameras[0] === undefined
|
|
3323
3359
|
? undefined
|
|
3324
3360
|
: resolveDepthOfFieldFrameParams(
|
|
3325
|
-
|
|
3326
|
-
|
|
3361
|
+
cameras[0].depthOfField,
|
|
3362
|
+
cameras[0].depthOfFieldError,
|
|
3327
3363
|
frameState.depthOfFieldAccepted?.params,
|
|
3328
3364
|
);
|
|
3329
3365
|
const submittedDepthOfFieldGraph = frameState.compiledFrameGraph?.inspect();
|
|
@@ -3341,7 +3377,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3341
3377
|
frameState.depthOfFieldLastSubmitFailed = true;
|
|
3342
3378
|
}
|
|
3343
3379
|
internals.getPipelineState()?.perPassResources.commitBloomResources?.();
|
|
3344
|
-
const nextBloom =
|
|
3380
|
+
const nextBloom = bloomAdmitted ? 'on' : 'off';
|
|
3345
3381
|
if (frameState.lastSuccessfulBloom === 'on' && nextBloom !== 'on') {
|
|
3346
3382
|
internals
|
|
3347
3383
|
.getPipelineState()
|
|
@@ -3406,6 +3442,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3406
3442
|
}),
|
|
3407
3443
|
);
|
|
3408
3444
|
} finally {
|
|
3445
|
+
if (!submitted) persistentRenderScene.discardTemporalFrame();
|
|
3409
3446
|
internals.recoveryColdWorkGuard?.endFrame();
|
|
3410
3447
|
if (ownsProfileFrame) {
|
|
3411
3448
|
try {
|
|
@@ -3419,18 +3456,67 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3419
3456
|
},
|
|
3420
3457
|
isDynamicGeometryConsumed: (world, entity, meshHandle) =>
|
|
3421
3458
|
dynamicGeometryFrames.isConsumed(world, entity, meshHandle),
|
|
3459
|
+
dynamicGeometryRecordStageLane: (world, entity, meshHandle) =>
|
|
3460
|
+
dynamicGeometryFrames.recordStageLane(world, entity, meshHandle),
|
|
3422
3461
|
pipelineDispatchCounts: dispatchCounts,
|
|
3423
3462
|
observeCurrentFrame(options: FrameObservationOptions) {
|
|
3424
3463
|
const currentFrameId = frameState.frameNumber - 1;
|
|
3425
3464
|
return observeCurrentFrame(options, frameState.currentFrameObservationSource, currentFrameId);
|
|
3426
3465
|
},
|
|
3427
|
-
async observeLodOcclusion(
|
|
3466
|
+
async observeLodOcclusion(receipt?: {
|
|
3467
|
+
readonly frameId: number;
|
|
3468
|
+
readonly deviceGeneration: number;
|
|
3469
|
+
}): Promise<void> {
|
|
3470
|
+
const capturedInspection = lastLodOcclusionInspection;
|
|
3471
|
+
const capturedWorldAttachments = lastLodWorldAttachments;
|
|
3472
|
+
if (capturedInspection === undefined) return;
|
|
3473
|
+
if (
|
|
3474
|
+
receipt !== undefined &&
|
|
3475
|
+
(capturedInspection.submit.frameId !== receipt.frameId ||
|
|
3476
|
+
capturedInspection.submit.deviceGeneration !== receipt.deviceGeneration)
|
|
3477
|
+
)
|
|
3478
|
+
return;
|
|
3428
3479
|
await ensureOcclusionRuntime().waitForCompletions();
|
|
3429
|
-
|
|
3430
|
-
|
|
3480
|
+
if (lastLodOcclusionInspection !== capturedInspection) return;
|
|
3481
|
+
const selection = await gpuDrivenProduction.readLodSelection();
|
|
3482
|
+
if (lastLodOcclusionInspection !== capturedInspection || selection === undefined) return;
|
|
3483
|
+
if (
|
|
3484
|
+
selection.submit !== undefined &&
|
|
3485
|
+
(selection.submit.frameId !== capturedInspection.submit.frameId ||
|
|
3486
|
+
selection.submit.deviceGeneration !== capturedInspection.submit.deviceGeneration)
|
|
3487
|
+
)
|
|
3488
|
+
return;
|
|
3489
|
+
if (
|
|
3490
|
+
receipt !== undefined &&
|
|
3491
|
+
(selection.submit === undefined ||
|
|
3492
|
+
selection.submit.frameId !== receipt.frameId ||
|
|
3493
|
+
selection.submit.deviceGeneration !== receipt.deviceGeneration)
|
|
3494
|
+
)
|
|
3495
|
+
return;
|
|
3496
|
+
applyLodSelectionTelemetry(selection, capturedInspection, capturedWorldAttachments);
|
|
3497
|
+
if (
|
|
3498
|
+
selection.surfaceReadback !== undefined &&
|
|
3499
|
+
selection.surfaceActualMemberIds !== undefined &&
|
|
3500
|
+
selection.surfaceIndirectParameters !== undefined
|
|
3501
|
+
) {
|
|
3502
|
+
surfaceSubmissionObservation.publishGpuMembers(
|
|
3503
|
+
{
|
|
3504
|
+
recording: selection.surfaceReadback,
|
|
3505
|
+
memberIds: selection.surfaceActualMemberIds,
|
|
3506
|
+
indirectParameters: selection.surfaceIndirectParameters,
|
|
3507
|
+
},
|
|
3508
|
+
receipt ?? capturedInspection.submit,
|
|
3509
|
+
);
|
|
3510
|
+
}
|
|
3511
|
+
const published = lastLodOcclusionInspection;
|
|
3512
|
+
if (
|
|
3513
|
+
published !== undefined &&
|
|
3514
|
+
published.submit.frameId === capturedInspection.submit.frameId &&
|
|
3515
|
+
published.submit.deviceGeneration === capturedInspection.submit.deviceGeneration
|
|
3516
|
+
) {
|
|
3431
3517
|
const queryLatency = ensureOcclusionRuntime().inspectQueryLatency();
|
|
3432
3518
|
lastLodOcclusionInspection = inspectLodOcclusion({
|
|
3433
|
-
...
|
|
3519
|
+
...published,
|
|
3434
3520
|
queryLatencyUs: {
|
|
3435
3521
|
median: queryLatency.median,
|
|
3436
3522
|
p95: queryLatency.p95,
|
|
@@ -3486,9 +3572,18 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3486
3572
|
get lastSuccessfulCameraAntialias(): CameraSnapshot['antialias'] | undefined {
|
|
3487
3573
|
return frameState.lastSuccessfulCameraAntialias;
|
|
3488
3574
|
},
|
|
3575
|
+
get lastSuccessfulBarrelDistortion(): BarrelDistortionMapping | undefined {
|
|
3576
|
+
return frameState.lastSuccessfulBarrelDistortion;
|
|
3577
|
+
},
|
|
3578
|
+
get barrelDistortionInspection(): BarrelDistortionInspection {
|
|
3579
|
+
return inspectBarrelDistortionState(frameState, internals.deviceScope?.generation ?? 0);
|
|
3580
|
+
},
|
|
3489
3581
|
get perFrameGraphInfo(): CompiledRenderGraphInfo | undefined {
|
|
3490
3582
|
return frameState.compiledFrameGraph?.inspect();
|
|
3491
3583
|
},
|
|
3584
|
+
get renderGraphGenerationAllocation() {
|
|
3585
|
+
return inspectRenderGraphGenerationAllocation(frameState);
|
|
3586
|
+
},
|
|
3492
3587
|
get featureGraphInspection(): import('./inspection-types').RenderFeatureGraphInspection {
|
|
3493
3588
|
return getRenderFeatureGraphInspection(internals);
|
|
3494
3589
|
},
|
|
@@ -3515,7 +3610,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3515
3610
|
});
|
|
3516
3611
|
},
|
|
3517
3612
|
get volumetricFog(): import('./volume/inspection').VolumetricFogInspection {
|
|
3518
|
-
|
|
3613
|
+
const accepted = frameState.volumetricFogAccepted;
|
|
3614
|
+
return {
|
|
3615
|
+
...frameState.volumetricFogInspection,
|
|
3616
|
+
ownerCount: accepted === undefined ? 0 : 1 + (accepted.additional?.length ?? 0),
|
|
3617
|
+
};
|
|
3519
3618
|
},
|
|
3520
3619
|
configureStandard(config: RenderPipelineAsset['config']): void {
|
|
3521
3620
|
const profileConfig = internals.standardProfile;
|
|
@@ -3594,7 +3693,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3594
3693
|
}
|
|
3595
3694
|
builtinPostProcessEntries.set(id, entry);
|
|
3596
3695
|
if (paramsBuffer !== undefined) postProcessParamsBuffers.set(id, paramsBuffer);
|
|
3597
|
-
const moduleLabel = postProcessShaderModuleLabel(
|
|
3696
|
+
const moduleLabel = postProcessShaderModuleLabel(entry.source);
|
|
3598
3697
|
return () => {
|
|
3599
3698
|
if (builtinPostProcessEntries.get(id) === entry) {
|
|
3600
3699
|
builtinPostProcessEntries.delete(id);
|
|
@@ -3643,6 +3742,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3643
3742
|
internals.getPipelineState()?.perPassResources.drainBloomResources?.();
|
|
3644
3743
|
internals.clearPostProcessPipelineCache?.('forgeax.taa-resolve');
|
|
3645
3744
|
invalidatePostProcessModule('forgeax.taa-resolve');
|
|
3745
|
+
// Post-process parameter UBOs are renderer-owned persistent resources,
|
|
3746
|
+
// rather than graph-owned transient state. Clear the active table before
|
|
3747
|
+
// the feature host is retired so the renderer remains the sole owner.
|
|
3748
|
+
disposeActivePostProcessResources();
|
|
3749
|
+
resetSsaoResources(internals);
|
|
3646
3750
|
resetHdrpBuffers(internals);
|
|
3647
3751
|
// Retire graph-owned resources and dispose instance-buffer caches.
|
|
3648
3752
|
// Both calls are idempotent + tolerate per-handle errors silently;
|
|
@@ -3654,6 +3758,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3654
3758
|
frameState.directionalShadowCacheRecorded = false;
|
|
3655
3759
|
frameState.currentFrameObservationSource = undefined;
|
|
3656
3760
|
frameState.lastSuccessfulCameraAntialias = undefined;
|
|
3761
|
+
frameState.lastSuccessfulBarrelDistortion = undefined;
|
|
3762
|
+
frameState.cloudHistoryActive = false;
|
|
3763
|
+
delete frameState.pendingCloudHistoryActive;
|
|
3657
3764
|
frameState.currentDirectionalShadowView = null;
|
|
3658
3765
|
frameState.currentSpotShadowView = null;
|
|
3659
3766
|
if (frameState.pendingAutoExposureGpuResources !== undefined) {
|
|
@@ -3681,6 +3788,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3681
3788
|
retireTemporalGpuState(retiring);
|
|
3682
3789
|
}
|
|
3683
3790
|
frameState.retiringTemporalGpuStates.clear();
|
|
3791
|
+
settleBarrelDistortionGraphCandidate(frameState, false);
|
|
3684
3792
|
settleVolumetricFogGraphCandidate(frameState, false);
|
|
3685
3793
|
for (const buffer of frameState.volumetricFogParamsBuffers) {
|
|
3686
3794
|
if (buffer === null) continue;
|
|
@@ -3714,9 +3822,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3714
3822
|
frameState.depthOfFieldCandidateGraph = null;
|
|
3715
3823
|
frameState.depthOfFieldAccepted = undefined;
|
|
3716
3824
|
frameState.depthOfFieldLastSubmitFailed = false;
|
|
3717
|
-
|
|
3825
|
+
resetBarrelDistortionGraphState(frameState);
|
|
3826
|
+
if (compiled !== null) retireCompiledGraph(frameState, compiled);
|
|
3718
3827
|
for (const retired of frameState.retiredCompiledFrameGraphs) {
|
|
3719
|
-
|
|
3828
|
+
retireCompiledGraph(frameState, retired);
|
|
3720
3829
|
}
|
|
3721
3830
|
frameState.retiredCompiledFrameGraphs.clear();
|
|
3722
3831
|
// feat-20260619 M4 (D-6): pass errorRegistry to disposeInstanceBuffers
|
|
@@ -3736,6 +3845,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3736
3845
|
}
|
|
3737
3846
|
frameState.probeBlendRecordBufferCapacity = 0;
|
|
3738
3847
|
frameState.probeBlendBuffers.clear();
|
|
3848
|
+
delete frameState.probeBlendRecordProjection;
|
|
3739
3849
|
if (frameState.morphBuffers !== undefined) {
|
|
3740
3850
|
for (const entry of frameState.morphBuffers.values()) {
|
|
3741
3851
|
if (!entry.buffer.isDestroyed) {
|
|
@@ -3774,6 +3884,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3774
3884
|
// device. Drop the shared Standard Cluster bundle before the next
|
|
3775
3885
|
// frame asks for a new generation; resetHdrpBuffers fences the bundle
|
|
3776
3886
|
// using its own device/queue instead of the replacement runtime device.
|
|
3887
|
+
resetSsaoResources(internals);
|
|
3777
3888
|
resetHdrpBuffers(internals);
|
|
3778
3889
|
// Keep the persistent material demand observable across device loss.
|
|
3779
3890
|
// The physical resource has already been fenced by markDeviceLost(); the
|
|
@@ -3814,9 +3925,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3814
3925
|
// must be discarded, not merely marked for destruction: their opaque
|
|
3815
3926
|
// handles cannot be used on the fresh device and the next draw must
|
|
3816
3927
|
// lazily build a new graph from the preserved ECS / asset POD caches.
|
|
3928
|
+
settleBarrelDistortionGraphCandidate(frameState, false);
|
|
3817
3929
|
settleVolumetricFogGraphCandidate(frameState, false);
|
|
3818
3930
|
settleDepthOfFieldGraphCandidate(frameState, false);
|
|
3819
|
-
frameState.compiledFrameGraph
|
|
3931
|
+
if (frameState.compiledFrameGraph !== null) {
|
|
3932
|
+
retireCompiledGraph(frameState, frameState.compiledFrameGraph);
|
|
3933
|
+
}
|
|
3820
3934
|
frameState.compiledFrameGraph = null;
|
|
3821
3935
|
frameState.compiledFrameGraphTopologyKey = null;
|
|
3822
3936
|
frameState.volumetricFogPreviousGraph = null;
|
|
@@ -3828,6 +3942,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3828
3942
|
frameState.depthOfFieldPreviousGraphGeneration = 0;
|
|
3829
3943
|
frameState.depthOfFieldPreviousStandardLightingGraphSignature = '';
|
|
3830
3944
|
frameState.depthOfFieldCandidateGraph = null;
|
|
3945
|
+
resetBarrelDistortionGraphState(frameState);
|
|
3831
3946
|
frameState.volumetricFogAccepted = undefined;
|
|
3832
3947
|
frameState.volumetricFogAcceptedContext = undefined;
|
|
3833
3948
|
frameState.volumetricFogHistoryGraph = null;
|
|
@@ -3854,6 +3969,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3854
3969
|
frameState.directionalShadowCacheRecorded = false;
|
|
3855
3970
|
frameState.currentFrameObservationSource = undefined;
|
|
3856
3971
|
frameState.lastSuccessfulCameraAntialias = undefined;
|
|
3972
|
+
frameState.lastSuccessfulBarrelDistortion = undefined;
|
|
3973
|
+
frameState.cloudHistoryActive = false;
|
|
3974
|
+
delete frameState.pendingCloudHistoryActive;
|
|
3857
3975
|
frameState.temporalFrameTransaction.reset('device-recovery');
|
|
3858
3976
|
frameState.temporalFrame = undefined;
|
|
3859
3977
|
frameState.temporalFrameInput = undefined;
|
|
@@ -3876,7 +3994,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3876
3994
|
frameState.retiringTemporalGpuStates.clear();
|
|
3877
3995
|
frameState.hdrpClusterMembership = null;
|
|
3878
3996
|
for (const retired of frameState.retiredCompiledFrameGraphs) {
|
|
3879
|
-
|
|
3997
|
+
retireCompiledGraph(frameState, retired);
|
|
3880
3998
|
}
|
|
3881
3999
|
frameState.retiredCompiledFrameGraphs.clear();
|
|
3882
4000
|
frameState.instanceBuffers.clear();
|
|
@@ -3885,6 +4003,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3885
4003
|
delete frameState.probeBlendRecordBuffer;
|
|
3886
4004
|
frameState.probeBlendRecordBufferCapacity = 0;
|
|
3887
4005
|
frameState.probeBlendBuffers.clear();
|
|
4006
|
+
delete frameState.probeBlendRecordProjection;
|
|
3888
4007
|
frameState.morphBuffers?.clear();
|
|
3889
4008
|
frameState.transientInstanceBuffers = [];
|
|
3890
4009
|
frameState.pointShadowAtlas = null;
|