@forgeax/engine-render 0.1.33 → 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 +1010 -124
- 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/host-contract.d.ts +3 -3
- package/dist/assembly/host-contract.d.ts.map +1 -1
- 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/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/webgpu-pbr-ready.d.ts +1 -0
- package/dist/assembly/webgpu-pbr-ready.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 +1 -1
- 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/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
- package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
- package/dist/{chunk-ZDQWGQW7.mjs → chunk-HEB564WF.mjs} +4 -4
- package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-HEB564WF.mjs.map} +1 -1
- package/dist/{chunk-VOZWDM3L.mjs → chunk-MKDIT2EM.mjs} +1307 -188
- package/dist/chunk-MKDIT2EM.mjs.map +1 -0
- package/dist/{chunk-LEAXOMYJ.mjs → chunk-OCDLEI6I.mjs} +3 -3
- package/dist/{chunk-LEAXOMYJ.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-3RTCJTH4.mjs → chunk-SHFUFJ5N.mjs} +184 -13
- package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
- package/dist/{chunk-OO3DRYK7.mjs → chunk-UI5SFODX.mjs} +176 -96
- package/dist/chunk-UI5SFODX.mjs.map +1 -0
- package/dist/{chunk-PLAXOOX5.mjs → chunk-UINHLCZA.mjs} +561 -79
- package/dist/chunk-UINHLCZA.mjs.map +1 -0
- package/dist/{chunk-NB2S7ZRX.mjs → chunk-WEX45HKH.mjs} +127 -386
- 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/barrel-distortion.d.ts +13 -0
- package/dist/components/barrel-distortion.d.ts.map +1 -0
- 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/construct-renderer.d.ts +1 -1
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +6759 -2875
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/dynamic-geometry.d.ts +5 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/errors/cloud.d.ts +59 -0
- package/dist/errors/cloud.d.ts.map +1 -0
- package/dist/errors/render.d.ts +18 -4
- 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 +5 -1
- package/dist/extract/contracts.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 +6 -2
- package/dist/features/error-reporting.d.ts.map +1 -1
- package/dist/features/host.d.ts +10 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/plan.d.ts +8 -0
- package/dist/features/plan.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.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 +47 -3
- 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 +26 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +5 -0
- 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 +27 -7
- 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 +135 -1
- 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 +48 -100
- 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.map +1 -1
- package/dist/pipeline-builder.d.ts +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- 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 +37 -3
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +10 -61
- 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/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 +22 -3
- 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 +1 -1
- 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 +42 -4
- 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 +103 -2
- 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 +16 -9
- 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 +19 -14
- 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 +12 -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/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/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 +14 -2
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +9 -4
- 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/package.json +22 -21
- 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__/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__/factory-contract.integration.test.ts +295 -45
- package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
- 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-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 +6 -5
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
- 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-scene.unit.test.ts +119 -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 +97 -305
- 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__/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 +13 -7
- 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-graphics-capability.unit.test.ts +66 -2
- package/src/__tests__/probe-bindings.unit.test.ts +582 -1
- package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
- 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 +7 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
- package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
- 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-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 +20 -20
- 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 +26 -10
- package/src/__tests__/resource-allocation.unit.test.ts +123 -0
- 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 +15 -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-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.integration.test.ts +182 -1
- 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__/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 +4 -2
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
- 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 +113 -9
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
- 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/host-contract.ts +3 -3
- 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/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 +4 -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 +3 -3
- package/src/assembly/webgpu-pbr-ready.ts +9 -1
- package/src/assembly/webgpu-ready-per-pass.ts +104 -0
- package/src/assembly/webgpu-ready.ts +115 -61
- 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 +214 -252
- package/src/assembly/webgpu-vertex-layouts.ts +1 -1
- package/src/barrel-distortion.ts +247 -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/barrel-distortion.ts +46 -0
- 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/sprite-instances.ts +1 -1
- package/src/construct-renderer.ts +1 -1
- package/src/dynamic-geometry.ts +12 -1
- package/src/errors/cloud.ts +103 -0
- package/src/errors/render.ts +44 -7
- package/src/examples/single-layer-medium-surface.ts +59 -0
- package/src/extract/camera.ts +15 -1
- package/src/extract/contracts.ts +5 -0
- package/src/features/barrel-distortion.ts +172 -0
- package/src/features/error-reporting.ts +26 -6
- package/src/features/host.ts +115 -14
- package/src/features/plan.ts +8 -0
- package/src/features/render-graph-contribution.ts +9 -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 +33 -25
- package/src/gpu-driven/prepared-draw.ts +12 -4
- package/src/gpu-driven/production-raster-material.ts +1894 -0
- package/src/gpu-driven/production-raster.ts +825 -784
- 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 +164 -10
- package/src/gpu-scene.ts +75 -84
- package/src/hdrp-buffers.ts +4 -3
- package/src/ibl/skylight-bind-group.ts +49 -7
- package/src/index.ts +196 -9
- package/src/inspection-types.ts +162 -0
- package/src/instance-buffer-cache.ts +4 -4
- package/src/instances.ts +149 -569
- 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 +90 -24
- package/src/pipeline-builder.ts +1 -1
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
- 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 +1 -1
- 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 +39 -3
- package/src/record/frame.ts +217 -1084
- package/src/record/gpu-draw-receipts.ts +38 -0
- package/src/record/gpu-timing.ts +48 -5
- package/src/record/main-pass-geometry.ts +251 -82
- package/src/record/main-pass-material.ts +66 -4
- package/src/record/main-pass-sprite-draws.ts +7 -65
- package/src/record/main-pass.ts +156 -20
- 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 +39 -3
- package/src/record/shadow-pass.ts +30 -1
- package/src/record/skybox-post-pass.ts +28 -4
- package/src/record/typed-frame-graph.ts +770 -134
- package/src/record/view-ubo.ts +26 -3
- package/src/record/volume-params.ts +225 -0
- package/src/recovery/render-system-candidate.ts +235 -42
- package/src/reflection/record-owner.ts +7 -3
- package/src/render-contract.ts +48 -4
- package/src/render-graph-primitives.ts +7 -1
- package/src/render-pipeline.ts +130 -0
- package/src/render-system-extract-tail.ts +57 -61
- package/src/render-system-extract.ts +74 -76
- 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 +347 -363
- package/src/scene/probe-blend.ts +96 -4
- package/src/scene/render-scene.ts +349 -280
- 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/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/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 +70 -2
- package/src/volume/component.ts +10 -9
- package/src/volume/extract.ts +11 -5
- package/src/volume/inspection.ts +3 -0
- package/src/volume/passes.ts +87 -4
- package/src/volume/resources.ts +2 -1
- package/dist/chunk-3RTCJTH4.mjs.map +0 -1
- package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
- package/dist/chunk-NNQL7CB3.mjs +0 -1713
- package/dist/chunk-NNQL7CB3.mjs.map +0 -1
- package/dist/chunk-OO3DRYK7.mjs.map +0 -1
- package/dist/chunk-PA5DRJNI.mjs.map +0 -1
- package/dist/chunk-PLAXOOX5.mjs.map +0 -1
- package/dist/chunk-VOZWDM3L.mjs.map +0 -1
package/src/render-system.ts
CHANGED
|
@@ -1,38 +1,18 @@
|
|
|
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,
|
|
@@ -40,7 +20,9 @@ import {
|
|
|
40
20
|
} from './assembly/directional-shadow-inspection';
|
|
41
21
|
import { createGpuDrivenOwner } from './assembly/gpu-driven-owner';
|
|
42
22
|
import { standardBloomAdmitted } from './bloom-admission';
|
|
23
|
+
import { createCloudFeatureFrameContext, createCloudFeatureView } from './cloud/frame-context';
|
|
43
24
|
import { createClusterBinScratch } from './cluster-binner';
|
|
25
|
+
import type { DynamicGeometryRecordStageLane } from './dynamic-geometry';
|
|
44
26
|
import { EnvironmentLifecycle } from './environment/lifecycle';
|
|
45
27
|
import {
|
|
46
28
|
type ObservationUnavailableError,
|
|
@@ -49,6 +31,7 @@ import {
|
|
|
49
31
|
} from './errors/render';
|
|
50
32
|
import { projectDepthOfFieldInspection } from './features/depth-of-field/depth-of-field-inspection';
|
|
51
33
|
import { resolveDepthOfFieldFrameParams } from './features/depth-of-field/depth-of-field-params';
|
|
34
|
+
import type { PendingRenderFeatureErrorReport } from './features/error-reporting';
|
|
52
35
|
import { reportPendingRenderFeatureErrors } from './features/error-reporting';
|
|
53
36
|
import {
|
|
54
37
|
type RenderFeaturePreparedGraphicsResolverInput,
|
|
@@ -83,6 +66,7 @@ import {
|
|
|
83
66
|
postProcessShaderPipelineLabel,
|
|
84
67
|
} from './fullscreen-post-process-pass';
|
|
85
68
|
import type {
|
|
69
|
+
BarrelDistortionInspection,
|
|
86
70
|
BloomInspection,
|
|
87
71
|
DepthOfFieldInspection,
|
|
88
72
|
DirectionalShadowInspection,
|
|
@@ -125,11 +109,7 @@ import {
|
|
|
125
109
|
} from './pipeline/standard-output/resources';
|
|
126
110
|
import type { PointsLinesRetainedSnapshot } from './points-lines/snapshot';
|
|
127
111
|
import { StandardPointsLinesOwner } from './points-lines/standard-owner';
|
|
128
|
-
import {
|
|
129
|
-
createRenderSystemRecovery,
|
|
130
|
-
materialSamplerHandles,
|
|
131
|
-
materialTextureHandles,
|
|
132
|
-
} from './recovery/render-system-candidate';
|
|
112
|
+
import { createRenderSystemRecovery } from './recovery/render-system-candidate';
|
|
133
113
|
|
|
134
114
|
export { materialTextureHandlesForResidency } from './recovery/render-system-candidate';
|
|
135
115
|
|
|
@@ -169,9 +149,10 @@ import { inspectVolumetricFog } from './volume/inspection';
|
|
|
169
149
|
|
|
170
150
|
export type { RenderSceneInspection } from './inspection-types';
|
|
171
151
|
|
|
152
|
+
import type { BarrelDistortionMapping } from './barrel-distortion';
|
|
172
153
|
import { createCubeCaptureScheduler } from './capture/scheduler';
|
|
173
154
|
import type { EnvironmentInspection } from './environment/inspection';
|
|
174
|
-
import {
|
|
155
|
+
import { rebaseShadowCasterOwnership } from './gpu-driven/shadow-ownership';
|
|
175
156
|
import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from './gpu-usage';
|
|
176
157
|
import { resetHdrpBuffers } from './hdrp-buffers';
|
|
177
158
|
import type { SkylightBindGroupResources } from './ibl/skylight-bind-group';
|
|
@@ -181,11 +162,9 @@ import {
|
|
|
181
162
|
disposeTransientInstanceBuffers,
|
|
182
163
|
} from './instance-buffer-cache';
|
|
183
164
|
import type { InstanceCollectionInspection } from './instances';
|
|
184
|
-
import {
|
|
165
|
+
import { InstanceProjectionStore } from './instances';
|
|
185
166
|
import {
|
|
186
167
|
type MeshMaterialBindingObservation,
|
|
187
|
-
type MeshMaterialBindingPreparationFailure,
|
|
188
|
-
type MeshMaterialBindingResidency,
|
|
189
168
|
projectMeshMaterialBindingObservation,
|
|
190
169
|
} from './mesh-material-bindings';
|
|
191
170
|
import type { StandardLightingInspection } from './pipeline/standard-lighting/inspection';
|
|
@@ -198,6 +177,10 @@ import {
|
|
|
198
177
|
createPreparedGraphicsResolver,
|
|
199
178
|
type PreparedGraphicsResolver,
|
|
200
179
|
} from './prepare/prepared-graphics-resolver';
|
|
180
|
+
import {
|
|
181
|
+
inspectBarrelDistortionState,
|
|
182
|
+
resetBarrelDistortionGraphState,
|
|
183
|
+
} from './record/barrel-distortion-frame';
|
|
201
184
|
import {
|
|
202
185
|
type CubeCaptureFrameInput,
|
|
203
186
|
type FrameObservation,
|
|
@@ -213,6 +196,7 @@ import type {
|
|
|
213
196
|
RenderFrameState,
|
|
214
197
|
} from './record/frame-snapshot';
|
|
215
198
|
import { getTextureIdentity, worldEntityKey } from './record/frame-snapshot';
|
|
199
|
+
import type { RenderableDrawReceipt } from './record/gpu-draw-receipts';
|
|
216
200
|
import type { GpuPassTimingReason } from './record/gpu-pass-timing/errors';
|
|
217
201
|
import type {
|
|
218
202
|
GpuPassTimingCapture,
|
|
@@ -230,34 +214,39 @@ import type { PipelineState, RenderSystemInternals } from './record/render-conte
|
|
|
230
214
|
import type { CubeCaptureGraphState } from './record/typed-frame-graph';
|
|
231
215
|
import {
|
|
232
216
|
getRenderFeatureGraphInspection,
|
|
217
|
+
inspectRenderGraphGenerationAllocation,
|
|
233
218
|
type RenderFeatureGraphCandidate,
|
|
234
219
|
recordRenderFeatureCandidate,
|
|
235
220
|
resetRenderFeatureGraphState,
|
|
221
|
+
retire as retireCompiledGraph,
|
|
222
|
+
settleBarrelDistortionGraphCandidate,
|
|
236
223
|
settleDepthOfFieldGraphCandidate,
|
|
237
224
|
settleVolumetricFogGraphCandidate,
|
|
238
225
|
} from './record/typed-frame-graph';
|
|
239
226
|
import {
|
|
240
227
|
type CameraSnapshot,
|
|
241
228
|
type DrawOwnerOptions,
|
|
229
|
+
type FramePresentation,
|
|
242
230
|
RENDER_PHASE_CATALOG,
|
|
243
231
|
type RenderPhase,
|
|
244
232
|
type RenderPhaseSkipReason,
|
|
245
233
|
type RenderRecordPhase,
|
|
246
234
|
} from './render-contract';
|
|
247
|
-
import type {
|
|
248
|
-
DispatchEntry,
|
|
249
|
-
ExtractedLights,
|
|
250
|
-
MaterialSnapshot,
|
|
251
|
-
RenderableSnapshot,
|
|
252
|
-
ShadowCasterMembership,
|
|
253
|
-
} from './render-system-extract';
|
|
235
|
+
import type { DispatchEntry, ExtractedLights, RenderableSnapshot } from './render-system-extract';
|
|
254
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';
|
|
255
242
|
import {
|
|
256
243
|
canonicalizeWorldComposition,
|
|
257
244
|
createLodWorldInspections,
|
|
258
245
|
} from './render-system-projections';
|
|
246
|
+
import { observeMaterialResidency } from './render-system-residency';
|
|
259
247
|
import { PersistentRenderScene } from './scene/render-scene';
|
|
260
248
|
import { inspectLodOcclusion } from './scene/visibility/inspection';
|
|
249
|
+
import { resetSsaoResources } from './ssao-buffers';
|
|
261
250
|
import { resolveSsaoParameters } from './ssao-config';
|
|
262
251
|
import {
|
|
263
252
|
projectSsrDependencies,
|
|
@@ -266,6 +255,8 @@ import {
|
|
|
266
255
|
zeroSsrAdmissionWork,
|
|
267
256
|
} from './ssr/admission';
|
|
268
257
|
import { projectSsrSpatialInspection } from './ssr/inspection';
|
|
258
|
+
import type { SurfaceDynamicInputFrame } from './surface/dynamic-input';
|
|
259
|
+
import { SurfaceSubmissionObservationOwner } from './surface/submission-observation';
|
|
269
260
|
import { sortTransparentDispatch } from './systems/transparent-dispatch';
|
|
270
261
|
import type { RenderTarget } from './targets/contracts';
|
|
271
262
|
import { createTemporalFrameTransaction, type TemporalFrame } from './temporal/frame';
|
|
@@ -283,73 +274,6 @@ import {
|
|
|
283
274
|
inspectTransmissionFromAdmission,
|
|
284
275
|
} from './transmission/inspection';
|
|
285
276
|
|
|
286
|
-
const WORLD_ENTITY_KEY_STRIDE = 4294967296;
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Extract emits world/entity keys in the transient `worlds[]` index domain,
|
|
290
|
-
* while PersistentRenderScene owns stable renderer-local World keys for the
|
|
291
|
-
* retained GPU scene. Rebase ShadowCaster ownership at this orchestration
|
|
292
|
-
* boundary before both GPU projection and CPU residual recording consume it.
|
|
293
|
-
*/
|
|
294
|
-
function rebaseShadowCasterOwnership(
|
|
295
|
-
worlds: readonly World[],
|
|
296
|
-
stableWorldKeys: readonly number[],
|
|
297
|
-
entityKeys: ReadonlySet<number>,
|
|
298
|
-
drawKeys: ReadonlySet<string>,
|
|
299
|
-
membership: readonly ShadowCasterMembership[] | undefined,
|
|
300
|
-
): {
|
|
301
|
-
readonly entityKeys: ReadonlySet<number>;
|
|
302
|
-
readonly drawKeys: ReadonlySet<string>;
|
|
303
|
-
readonly membership: readonly ShadowCasterMembership[] | undefined;
|
|
304
|
-
} {
|
|
305
|
-
const rebaseWorldEntity = (composite: number): number => {
|
|
306
|
-
const transientWorldId = Math.floor(composite / WORLD_ENTITY_KEY_STRIDE);
|
|
307
|
-
if (
|
|
308
|
-
!Number.isInteger(transientWorldId) ||
|
|
309
|
-
transientWorldId < 0 ||
|
|
310
|
-
transientWorldId >= worlds.length
|
|
311
|
-
) {
|
|
312
|
-
return composite;
|
|
313
|
-
}
|
|
314
|
-
const entityKey = composite - transientWorldId * WORLD_ENTITY_KEY_STRIDE;
|
|
315
|
-
return worldEntityKey(stableWorldKeys[transientWorldId] ?? transientWorldId, entityKey);
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
const stableMembership =
|
|
319
|
-
membership === undefined
|
|
320
|
-
? undefined
|
|
321
|
-
: membership.map((entry) => ({
|
|
322
|
-
...entry,
|
|
323
|
-
worldEntity: rebaseWorldEntity(entry.worldEntity),
|
|
324
|
-
}));
|
|
325
|
-
const stableDrawKeys =
|
|
326
|
-
stableMembership === undefined
|
|
327
|
-
? new Set(
|
|
328
|
-
[...drawKeys].map((key) => {
|
|
329
|
-
const parts = key.split(':');
|
|
330
|
-
if (parts.length !== 4) return key;
|
|
331
|
-
const transientWorldEntity = Number(parts[0]);
|
|
332
|
-
if (!Number.isFinite(transientWorldEntity)) return key;
|
|
333
|
-
return `${rebaseWorldEntity(transientWorldEntity)}:${parts[1]}:${parts[2]}:${parts[3]}`;
|
|
334
|
-
}),
|
|
335
|
-
)
|
|
336
|
-
: new Set(
|
|
337
|
-
stableMembership.map((entry) =>
|
|
338
|
-
gpuDrivenShadowDrawKey(
|
|
339
|
-
entry.worldEntity,
|
|
340
|
-
entry.materialHandle,
|
|
341
|
-
entry.drawItemIndex,
|
|
342
|
-
entry.passIndex,
|
|
343
|
-
),
|
|
344
|
-
),
|
|
345
|
-
);
|
|
346
|
-
return {
|
|
347
|
-
entityKeys: new Set([...entityKeys].map(rebaseWorldEntity)),
|
|
348
|
-
drawKeys: stableDrawKeys,
|
|
349
|
-
membership: stableMembership,
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
|
|
353
277
|
type TimingSessionHost = RenderSystemInternals & {
|
|
354
278
|
gpuPassTimingSession?: GpuPassTimingSession | undefined;
|
|
355
279
|
gpuPassTimingCapture?: GpuPassTimingCapture | undefined;
|
|
@@ -386,102 +310,11 @@ export {
|
|
|
386
310
|
selectSwapChainFormat,
|
|
387
311
|
} from './record/render-context';
|
|
388
312
|
|
|
389
|
-
export type
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
| 'gpu-driven'
|
|
395
|
-
| 'feature'
|
|
396
|
-
| 'external-source'
|
|
397
|
-
| 'render-graph'
|
|
398
|
-
| 'target-history'
|
|
399
|
-
| 'observation-lease';
|
|
400
|
-
|
|
401
|
-
export interface RendererProducerRoot {
|
|
402
|
-
readonly kind: RendererProducerRootKind;
|
|
403
|
-
readonly owner: string;
|
|
404
|
-
readonly candidateScope: 'device-scope';
|
|
405
|
-
readonly visibility: 'visible-workset' | 'non-visible-lazy';
|
|
406
|
-
readonly disabledWork: 'zero' | 'lazy';
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
const PRODUCER_ROOT_MATRIX: readonly RendererProducerRoot[] = Object.freeze([
|
|
410
|
-
{
|
|
411
|
-
kind: 'backend-surface',
|
|
412
|
-
owner: 'backend-surface-owner',
|
|
413
|
-
candidateScope: 'device-scope',
|
|
414
|
-
visibility: 'visible-workset',
|
|
415
|
-
disabledWork: 'zero',
|
|
416
|
-
},
|
|
417
|
-
{
|
|
418
|
-
kind: 'shader-material-pipeline',
|
|
419
|
-
owner: 'shader-material-pipeline-owner',
|
|
420
|
-
candidateScope: 'device-scope',
|
|
421
|
-
visibility: 'visible-workset',
|
|
422
|
-
disabledWork: 'zero',
|
|
423
|
-
},
|
|
424
|
-
{
|
|
425
|
-
kind: 'mesh-texture-sampler',
|
|
426
|
-
owner: 'gpu-residency',
|
|
427
|
-
candidateScope: 'device-scope',
|
|
428
|
-
visibility: 'visible-workset',
|
|
429
|
-
disabledWork: 'lazy',
|
|
430
|
-
},
|
|
431
|
-
{
|
|
432
|
-
kind: 'render-scene',
|
|
433
|
-
owner: 'persistent-render-scene',
|
|
434
|
-
candidateScope: 'device-scope',
|
|
435
|
-
visibility: 'visible-workset',
|
|
436
|
-
disabledWork: 'zero',
|
|
437
|
-
},
|
|
438
|
-
{
|
|
439
|
-
kind: 'gpu-driven',
|
|
440
|
-
owner: 'gpu-driven-production',
|
|
441
|
-
candidateScope: 'device-scope',
|
|
442
|
-
visibility: 'visible-workset',
|
|
443
|
-
disabledWork: 'zero',
|
|
444
|
-
},
|
|
445
|
-
{
|
|
446
|
-
kind: 'feature',
|
|
447
|
-
owner: 'render-feature-host',
|
|
448
|
-
candidateScope: 'device-scope',
|
|
449
|
-
visibility: 'visible-workset',
|
|
450
|
-
disabledWork: 'lazy',
|
|
451
|
-
},
|
|
452
|
-
{
|
|
453
|
-
kind: 'external-source',
|
|
454
|
-
owner: 'external-source-owner',
|
|
455
|
-
candidateScope: 'device-scope',
|
|
456
|
-
visibility: 'non-visible-lazy',
|
|
457
|
-
disabledWork: 'zero',
|
|
458
|
-
},
|
|
459
|
-
{
|
|
460
|
-
kind: 'render-graph',
|
|
461
|
-
owner: 'typed-frame-graph',
|
|
462
|
-
candidateScope: 'device-scope',
|
|
463
|
-
visibility: 'visible-workset',
|
|
464
|
-
disabledWork: 'zero',
|
|
465
|
-
},
|
|
466
|
-
{
|
|
467
|
-
kind: 'target-history',
|
|
468
|
-
owner: 'temporal-target-owner',
|
|
469
|
-
candidateScope: 'device-scope',
|
|
470
|
-
visibility: 'visible-workset',
|
|
471
|
-
disabledWork: 'zero',
|
|
472
|
-
},
|
|
473
|
-
{
|
|
474
|
-
kind: 'observation-lease',
|
|
475
|
-
owner: 'render-observation-owner',
|
|
476
|
-
candidateScope: 'device-scope',
|
|
477
|
-
visibility: 'non-visible-lazy',
|
|
478
|
-
disabledWork: 'zero',
|
|
479
|
-
},
|
|
480
|
-
]);
|
|
481
|
-
|
|
482
|
-
export function createRendererProducerRootMatrix(): readonly RendererProducerRoot[] {
|
|
483
|
-
return PRODUCER_ROOT_MATRIX;
|
|
484
|
-
}
|
|
313
|
+
export type {
|
|
314
|
+
RendererProducerRoot,
|
|
315
|
+
RendererProducerRootKind,
|
|
316
|
+
} from './render-system-producer-roots';
|
|
317
|
+
export { createRendererProducerRootMatrix } from './render-system-producer-roots';
|
|
485
318
|
|
|
486
319
|
/**
|
|
487
320
|
* Production-owned recovery facts. These values are projections of the live
|
|
@@ -520,6 +353,8 @@ export interface RecoveryProductionEvidence {
|
|
|
520
353
|
*/
|
|
521
354
|
export interface RenderSystem {
|
|
522
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;
|
|
523
358
|
/** Complete explicit SSR capability preparation before drawing a device generation. */
|
|
524
359
|
initializeSsr(device?: RhiDevice): Promise<void>;
|
|
525
360
|
/** Returns true only when this invocation reached queue submission. */
|
|
@@ -535,6 +370,11 @@ export interface RenderSystem {
|
|
|
535
370
|
* barrier; ECS component presence alone is not a draw receipt.
|
|
536
371
|
*/
|
|
537
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;
|
|
538
378
|
invalidateGeometryHistory(): void;
|
|
539
379
|
/** Prepare a detached graph candidate without entering the frame record path. */
|
|
540
380
|
prepareRecoveryGraphCandidate(
|
|
@@ -568,8 +408,6 @@ export interface RenderSystem {
|
|
|
568
408
|
readonly pipelineDispatchCounts: {
|
|
569
409
|
readonly unlit: number;
|
|
570
410
|
};
|
|
571
|
-
/** Renderer-owned source for explicit large instance collections. */
|
|
572
|
-
readonly instances: InstanceCollectionStore;
|
|
573
411
|
/** Detached residency and upload facts for explicit instance collections. */
|
|
574
412
|
readonly instanceCollectionsInspection: readonly InstanceCollectionInspection[];
|
|
575
413
|
/**
|
|
@@ -588,6 +426,8 @@ export interface RenderSystem {
|
|
|
588
426
|
readonly ssr: SsrSpatialInspection;
|
|
589
427
|
/** Producer completion fence included in the public FrameReceipt. */
|
|
590
428
|
readonly reflectionFallbackCompletion: Promise<void> | undefined;
|
|
429
|
+
/** Presentation readiness derived from the producer facts used by draw(). */
|
|
430
|
+
readonly presentation: FramePresentation;
|
|
591
431
|
/** True while a progressive CubeCamera candidate still owns unfinished faces. */
|
|
592
432
|
isCubeCapturePending(target: RenderTarget): boolean;
|
|
593
433
|
readonly environment: EnvironmentInspection;
|
|
@@ -630,8 +470,14 @@ export interface RenderSystem {
|
|
|
630
470
|
readonly perFramePassNames: readonly string[];
|
|
631
471
|
/** Camera antialias mode for the last successfully submitted frame. */
|
|
632
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;
|
|
633
477
|
/** Detached compiled-graph facts used by the renderer inspection owner. */
|
|
634
478
|
readonly perFrameGraphInfo: CompiledRenderGraphInfo | undefined;
|
|
479
|
+
/** Detached allocation facts across active, candidate, and retiring graphs. */
|
|
480
|
+
readonly renderGraphGenerationAllocation: import('@forgeax/engine-render-graph').RenderGraphGenerationAllocationInspection;
|
|
635
481
|
/** Detached feature signature/compile/lifetime counters. */
|
|
636
482
|
readonly featureGraphInspection: import('./inspection-types').RenderFeatureGraphInspection;
|
|
637
483
|
/** Detached material texture-source probe counters from the last extract. */
|
|
@@ -751,149 +597,6 @@ function makePreparedPipelinePendingError(): RhiError {
|
|
|
751
597
|
});
|
|
752
598
|
}
|
|
753
599
|
|
|
754
|
-
function preparationFailureFrom(error: unknown): MeshMaterialBindingPreparationFailure | undefined {
|
|
755
|
-
if (typeof error !== 'object' || error === null) return undefined;
|
|
756
|
-
const value = error as {
|
|
757
|
-
readonly code?: unknown;
|
|
758
|
-
readonly expected?: unknown;
|
|
759
|
-
readonly hint?: unknown;
|
|
760
|
-
readonly detail?: unknown;
|
|
761
|
-
};
|
|
762
|
-
if (
|
|
763
|
-
typeof value.code !== 'string' ||
|
|
764
|
-
typeof value.expected !== 'string' ||
|
|
765
|
-
typeof value.hint !== 'string'
|
|
766
|
-
) {
|
|
767
|
-
return undefined;
|
|
768
|
-
}
|
|
769
|
-
const detail =
|
|
770
|
-
typeof value.detail === 'object' && value.detail !== null
|
|
771
|
-
? { ...(value.detail as Record<string, unknown>) }
|
|
772
|
-
: undefined;
|
|
773
|
-
return {
|
|
774
|
-
code: value.code,
|
|
775
|
-
expected: value.expected,
|
|
776
|
-
hint: value.hint,
|
|
777
|
-
...(detail === undefined ? {} : { detail }),
|
|
778
|
-
};
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
/**
|
|
782
|
-
* Project the producer-owned material and GPU store state into the one
|
|
783
|
-
* renderer observation surface. This is intentionally recomputed from the
|
|
784
|
-
* current frame's detached material snapshots; no readiness map is retained
|
|
785
|
-
* by RenderSystem. A producer failure with an already resident resource is
|
|
786
|
-
* reported as last-known-good, preserving recovery context without copying
|
|
787
|
-
* the producer's lifecycle state.
|
|
788
|
-
*/
|
|
789
|
-
function observeMaterialResidency(
|
|
790
|
-
world: World | undefined,
|
|
791
|
-
material: MaterialSnapshot,
|
|
792
|
-
internals: RenderSystemInternals,
|
|
793
|
-
): MeshMaterialBindingResidency {
|
|
794
|
-
const textures: Array<{ readonly handle: number; readonly mipLevelCount: number }> = [];
|
|
795
|
-
const samplers: Array<{ readonly handle: number; readonly resident: boolean }> = [];
|
|
796
|
-
let pending = false;
|
|
797
|
-
let resident = false;
|
|
798
|
-
let failure: MeshMaterialBindingPreparationFailure | undefined;
|
|
799
|
-
const keepFailure = (error: unknown): void => {
|
|
800
|
-
if (failure === undefined) failure = preparationFailureFrom(error);
|
|
801
|
-
};
|
|
802
|
-
|
|
803
|
-
if (world === undefined) {
|
|
804
|
-
pending = true;
|
|
805
|
-
} else {
|
|
806
|
-
const materialHandle = material.materialHandle;
|
|
807
|
-
if (materialHandle !== undefined && materialHandle !== 0) {
|
|
808
|
-
const materialResult = resolveAssetHandle<MaterialAsset>(
|
|
809
|
-
world,
|
|
810
|
-
toShared<'MaterialAsset'>(materialHandle),
|
|
811
|
-
);
|
|
812
|
-
if (!materialResult.ok) {
|
|
813
|
-
keepFailure(materialResult.error);
|
|
814
|
-
} else {
|
|
815
|
-
const guid = internals.assets.guidOf(materialResult.value);
|
|
816
|
-
if (guid !== undefined) {
|
|
817
|
-
const readiness = internals.assets.getMaterialReadiness(guid);
|
|
818
|
-
if (readiness?.status === 'Error') keepFailure(readiness.error);
|
|
819
|
-
const load = internals.assets.loadState.get(guid);
|
|
820
|
-
if (load?.status === 'provisional') pending = true;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
for (const handle of materialTextureHandles(material)) {
|
|
826
|
-
const existing = internals.gpuStore.getTextureGpuView(handle, world);
|
|
827
|
-
const pod = resolveAssetHandle<TextureAsset>(world, handle);
|
|
828
|
-
if (!pod.ok) {
|
|
829
|
-
keepFailure(pod.error);
|
|
830
|
-
continue;
|
|
831
|
-
}
|
|
832
|
-
let view = existing;
|
|
833
|
-
if (view === undefined) {
|
|
834
|
-
const prepared = internals.gpuStore.ensureResident(handle, pod.value, world);
|
|
835
|
-
if (!prepared.ok) keepFailure(prepared.error);
|
|
836
|
-
view = internals.gpuStore.getTextureGpuView(handle, world);
|
|
837
|
-
}
|
|
838
|
-
if (view === undefined) {
|
|
839
|
-
pending = failure === undefined;
|
|
840
|
-
continue;
|
|
841
|
-
}
|
|
842
|
-
const textureLayout = deriveTextureLayout({
|
|
843
|
-
shape: pod.value.shape,
|
|
844
|
-
format: pod.value.format,
|
|
845
|
-
mips: pod.value.mips,
|
|
846
|
-
});
|
|
847
|
-
if (!textureLayout.ok) {
|
|
848
|
-
keepFailure(textureLayout.error);
|
|
849
|
-
continue;
|
|
850
|
-
}
|
|
851
|
-
resident = true;
|
|
852
|
-
textures.push({
|
|
853
|
-
handle: Number(handle),
|
|
854
|
-
mipLevelCount: Math.max(1, textureLayout.value.levels.length),
|
|
855
|
-
});
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
for (const handle of materialSamplerHandles(material)) {
|
|
859
|
-
const pod = resolveAssetHandle<SamplerAsset>(world, handle);
|
|
860
|
-
if (!pod.ok) {
|
|
861
|
-
keepFailure(pod.error);
|
|
862
|
-
samplers.push({ handle: Number(handle), resident: false });
|
|
863
|
-
continue;
|
|
864
|
-
}
|
|
865
|
-
const prepared = internals.gpuStore.ensureSamplerResident(handle, pod.value, world);
|
|
866
|
-
if (!prepared.ok) {
|
|
867
|
-
keepFailure(prepared.error);
|
|
868
|
-
samplers.push({ handle: Number(handle), resident: false });
|
|
869
|
-
} else {
|
|
870
|
-
resident = true;
|
|
871
|
-
samplers.push({ handle: Number(handle), resident: true });
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
// Video views are supplied by the dynamic host store at record time. They
|
|
875
|
-
// are not static TextureAsset residents, so this bounded projection stays
|
|
876
|
-
// pending until a dynamic observation contract exists rather than guessing
|
|
877
|
-
// from the VideoAsset GUID.
|
|
878
|
-
if ((material.videoTextureFields?.size ?? 0) > 0) pending = true;
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
const readiness =
|
|
882
|
-
failure === undefined
|
|
883
|
-
? pending
|
|
884
|
-
? 'pending'
|
|
885
|
-
: 'ready'
|
|
886
|
-
: resident
|
|
887
|
-
? 'last-known-good'
|
|
888
|
-
: 'failed';
|
|
889
|
-
return {
|
|
890
|
-
readiness,
|
|
891
|
-
samplers,
|
|
892
|
-
textures,
|
|
893
|
-
...(failure === undefined ? {} : { preparationFailure: failure }),
|
|
894
|
-
};
|
|
895
|
-
}
|
|
896
|
-
|
|
897
600
|
export function createRenderSystem(internals: RenderSystemInternals): RenderSystem {
|
|
898
601
|
const phaseCatalogRegistration = internals.profiler?.registerPhaseCatalog(
|
|
899
602
|
'render',
|
|
@@ -909,6 +612,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
909
612
|
});
|
|
910
613
|
let preparedFeatureSkylightResources: SkylightBindGroupResources | undefined;
|
|
911
614
|
const dynamicGeometryFrames = createDynamicGeometryFrameBindings();
|
|
615
|
+
let surfaceDynamicInputFrame: SurfaceDynamicInputFrame | undefined;
|
|
912
616
|
let latestCamera: CameraSnapshot | undefined;
|
|
913
617
|
// Last public parameter failure; cleared only after a valid extraction.
|
|
914
618
|
let lastMotionBlurInvalidParams: MotionBlurValidationError | undefined;
|
|
@@ -929,7 +633,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
929
633
|
if (!installed.ok) internals.errorRegistry.fire(installed.error);
|
|
930
634
|
};
|
|
931
635
|
const pointsLinesOwner = new StandardPointsLinesOwner(internals);
|
|
932
|
-
const instanceCollections = new
|
|
636
|
+
const instanceCollections = new InstanceProjectionStore();
|
|
933
637
|
const reflectionProbeOwner = new ReflectionProbeRecordOwner(internals);
|
|
934
638
|
const ssrFormatReceipts = new WeakMap<
|
|
935
639
|
RhiDevice,
|
|
@@ -957,7 +661,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
957
661
|
const persistentRenderScene = new PersistentRenderScene({
|
|
958
662
|
getDevice: () => internals.device,
|
|
959
663
|
onGpuError: (error) => internals.errorRegistry.fire(error),
|
|
960
|
-
|
|
664
|
+
onRuntimeAssetChange: (worldId, handle) => {
|
|
961
665
|
internals.gpuStore.invalidateMesh(handle, preparedWorlds[worldId] ?? worldId);
|
|
962
666
|
},
|
|
963
667
|
instanceCollections,
|
|
@@ -1105,6 +809,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1105
809
|
),
|
|
1106
810
|
} satisfies import('./pipeline-builder').PipelineBuilderShaderModuleFactory);
|
|
1107
811
|
let gpuDrivenRecoveryCount = 0;
|
|
812
|
+
const surfaceSubmissionObservation = new SurfaceSubmissionObservationOwner(
|
|
813
|
+
() => internals.deviceScope.generation,
|
|
814
|
+
);
|
|
1108
815
|
let gpuDrivenProduction = createGpuDrivenOwner(
|
|
1109
816
|
internals.device,
|
|
1110
817
|
gpuDrivenShaderFactory,
|
|
@@ -1176,6 +883,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1176
883
|
// raw (material-handle-based, cross-world collision semantically correct).
|
|
1177
884
|
const frameState: RenderFrameState = {
|
|
1178
885
|
frameNumber: 0,
|
|
886
|
+
surfaceSubmissionObservation: undefined,
|
|
1179
887
|
reflectionFallbackDemand: false,
|
|
1180
888
|
ssrRequested: false,
|
|
1181
889
|
ssrSpatialAdmission: undefined,
|
|
@@ -1203,6 +911,13 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1203
911
|
depthOfFieldCandidateGraph: null,
|
|
1204
912
|
depthOfFieldAccepted: undefined,
|
|
1205
913
|
depthOfFieldLastSubmitFailed: false,
|
|
914
|
+
barrelDistortionPreviousGraph: null,
|
|
915
|
+
barrelDistortionPreviousGraphKey: null,
|
|
916
|
+
barrelDistortionPreviousPerFrameGraph: undefined,
|
|
917
|
+
barrelDistortionPreviousGraphGeneration: 0,
|
|
918
|
+
barrelDistortionPreviousCompiledGraphGeneration: 0,
|
|
919
|
+
barrelDistortionPreviousStandardLightingGraphSignature: '',
|
|
920
|
+
barrelDistortionCandidateGraph: null,
|
|
1206
921
|
volumetricFogPreviousGraph: null,
|
|
1207
922
|
volumetricFogPreviousGraphKey: null,
|
|
1208
923
|
volumetricFogCandidateGraph: null,
|
|
@@ -1221,6 +936,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1221
936
|
currentFrameObservationSource: undefined,
|
|
1222
937
|
reflectionFallbackObservationSource: undefined,
|
|
1223
938
|
lastSuccessfulCameraAntialias: undefined,
|
|
939
|
+
lastSuccessfulBarrelDistortion: undefined,
|
|
940
|
+
barrelDistortionGraphResolution: 'accepted',
|
|
1224
941
|
temporalGpuState: undefined,
|
|
1225
942
|
autoExposureGpuResources: undefined,
|
|
1226
943
|
pendingAutoExposureGpuResources: undefined,
|
|
@@ -1326,7 +1043,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1326
1043
|
// publish the same transient failure on every render tick. Keep one
|
|
1327
1044
|
// renderer-owned cooldown per structured feature failure while retaining
|
|
1328
1045
|
// the original error for the first and periodic reports.
|
|
1329
|
-
const pendingFeatureErrorLastReportedFrame = new Map<string,
|
|
1046
|
+
const pendingFeatureErrorLastReportedFrame = new Map<string, PendingRenderFeatureErrorReport>();
|
|
1330
1047
|
const resolveSsrDependencies = (requested: boolean): SsrDependenciesInspection => {
|
|
1331
1048
|
// Explicit SSR capability preparation belongs to initialization. Inspection
|
|
1332
1049
|
// only projects receipts and never starts work or creates image history.
|
|
@@ -1532,7 +1249,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1532
1249
|
const invalidatePostProcessModule = (id: string): void => {
|
|
1533
1250
|
const entry = lookupPostProcess(id);
|
|
1534
1251
|
if (entry !== undefined) {
|
|
1535
|
-
internals.invalidateShaderModule?.(postProcessShaderModuleLabel(
|
|
1252
|
+
internals.invalidateShaderModule?.(postProcessShaderModuleLabel(entry.source));
|
|
1536
1253
|
}
|
|
1537
1254
|
};
|
|
1538
1255
|
// feat-20260621 M-A2 / w8: expose the eager-created per-id params UBO through
|
|
@@ -1622,6 +1339,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1622
1339
|
if (!destroyed.ok) internals.errorRegistry.fire(destroyed.error);
|
|
1623
1340
|
}
|
|
1624
1341
|
};
|
|
1342
|
+
const disposeActivePostProcessResources = (): void => {
|
|
1343
|
+
const resources = { device: postProcessParamsDevice, paramsBuffers: postProcessParamsBuffers };
|
|
1344
|
+
postProcessParamsBuffers = new Map();
|
|
1345
|
+
disposePostProcessResources(resources);
|
|
1346
|
+
};
|
|
1625
1347
|
const preparePostProcessParamsResources = (
|
|
1626
1348
|
featureEntries: ReadonlyMap<string, PostProcessShaderEntry>,
|
|
1627
1349
|
): Result<PostProcessParamsCandidate, RhiError> => {
|
|
@@ -1901,6 +1623,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1901
1623
|
};
|
|
1902
1624
|
let lastMeshMaterialBindings: readonly MeshMaterialBindingObservation[] = [];
|
|
1903
1625
|
let lastMeshMaterialBindingRenderables: readonly RenderableSnapshot[] | undefined;
|
|
1626
|
+
let lastPresentation: FramePresentation = 'pending';
|
|
1904
1627
|
const createPreparedResolverFactory =
|
|
1905
1628
|
(
|
|
1906
1629
|
runtime: RenderSystemInternals,
|
|
@@ -2064,6 +1787,17 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2064
1787
|
) {
|
|
2065
1788
|
return err(new Error('prepared scene-depth pipeline requires a scene target'));
|
|
2066
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
|
+
}
|
|
2067
1801
|
if (preparedGroup0Pipelines.has(pipeline as object)) {
|
|
2068
1802
|
const layout =
|
|
2069
1803
|
(materialShaderId === undefined
|
|
@@ -2201,10 +1935,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2201
1935
|
createPreparedResolverCaches,
|
|
2202
1936
|
});
|
|
2203
1937
|
return {
|
|
2204
|
-
|
|
1938
|
+
setSurfaceDynamicInput(frame: SurfaceDynamicInputFrame | undefined): void {
|
|
1939
|
+
surfaceDynamicInputFrame = frame;
|
|
1940
|
+
},
|
|
2205
1941
|
initializeSsr: ensureSsrFormatProbe,
|
|
2206
1942
|
get instanceCollectionsInspection(): readonly InstanceCollectionInspection[] {
|
|
2207
|
-
return instanceCollections._inspections();
|
|
1943
|
+
return instanceCollections._inspections(frameState.frameNumber - 1);
|
|
2208
1944
|
},
|
|
2209
1945
|
releaseProfilerCatalog(): void {
|
|
2210
1946
|
releaseProfilerCatalog?.();
|
|
@@ -2217,9 +1953,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2217
1953
|
return persistentRenderScene.bounds(world, entity);
|
|
2218
1954
|
},
|
|
2219
1955
|
get renderScene(): RenderSceneInspection {
|
|
1956
|
+
const submission = surfaceSubmissionObservation.inspect();
|
|
2220
1957
|
return {
|
|
2221
1958
|
...persistentRenderScene.inspect(),
|
|
2222
1959
|
gpuDriven: gpuDrivenProduction.inspect(),
|
|
1960
|
+
...(submission === undefined ? {} : { submission }),
|
|
2223
1961
|
};
|
|
2224
1962
|
},
|
|
2225
1963
|
get gpuDrivenInspection(): GpuDrivenProductionInspection {
|
|
@@ -2274,6 +2012,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2274
2012
|
get reflectionFallbackCompletion(): Promise<void> | undefined {
|
|
2275
2013
|
return frameState.reflectionFallbackCompletion;
|
|
2276
2014
|
},
|
|
2015
|
+
get presentation(): FramePresentation {
|
|
2016
|
+
return lastPresentation;
|
|
2017
|
+
},
|
|
2277
2018
|
isCubeCapturePending(target: RenderTarget): boolean {
|
|
2278
2019
|
return cubeCaptureScheduler.inspect(target).candidateGeneration !== undefined;
|
|
2279
2020
|
},
|
|
@@ -2465,6 +2206,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2465
2206
|
const profileSession = internals.profiler?.activeSession();
|
|
2466
2207
|
let ownsProfileFrame = false;
|
|
2467
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';
|
|
2468
2213
|
// A prior failed record/submit may have staged a temporal capture. A
|
|
2469
2214
|
// capture belongs only to the draw call that created it; discard it
|
|
2470
2215
|
// before this call can prepare or commit a new candidate.
|
|
@@ -2568,6 +2313,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2568
2313
|
environment,
|
|
2569
2314
|
environmentReady,
|
|
2570
2315
|
volumetricFog,
|
|
2316
|
+
cloudLayer,
|
|
2571
2317
|
renderables,
|
|
2572
2318
|
dispatch,
|
|
2573
2319
|
shadowCasterEntityKeys: extractedShadowCasterEntityKeys,
|
|
@@ -2796,6 +2542,17 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2796
2542
|
);
|
|
2797
2543
|
const submissionRenderables = visibilityProjection.renderables;
|
|
2798
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;
|
|
2799
2556
|
const inspectionCamera = latestCamera;
|
|
2800
2557
|
// The public frame receipt is allocated by WebGPURenderer immediately
|
|
2801
2558
|
// before this draw (`observationFrameId`). RenderSystem's private
|
|
@@ -2991,6 +2748,17 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2991
2748
|
bindGroupCounts.createBindGroup = 0;
|
|
2992
2749
|
bindGroupCounts.keys = [];
|
|
2993
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
|
+
);
|
|
2994
2762
|
const bindGroupSkipReason: RenderPhaseSkipReason | undefined =
|
|
2995
2763
|
internals.featureHost === undefined
|
|
2996
2764
|
? 'feature-host-unavailable'
|
|
@@ -3041,6 +2809,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3041
2809
|
colorAttachmentFormat: preparedPipelineState.colorAttachmentFormat,
|
|
3042
2810
|
storageBuffer: internals.device.caps.storageBuffer,
|
|
3043
2811
|
multisample: internals.device.caps.backendKind !== 'wgpu-webgl2',
|
|
2812
|
+
cloudHistory: cloudLayer !== undefined,
|
|
3044
2813
|
});
|
|
3045
2814
|
const motionBlurParams = cameras[0]?.motionBlur;
|
|
3046
2815
|
let motionBlurDelta = 0;
|
|
@@ -3092,12 +2861,14 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3092
2861
|
worlds: compositionWorlds,
|
|
3093
2862
|
owner: resourceOwner,
|
|
3094
2863
|
frameNumber: frameState.frameNumber,
|
|
2864
|
+
...(cameras[0] === undefined ? {} : { selectedCamera: cameras[0] }),
|
|
3095
2865
|
frameSize: { width: internals.canvas.width, height: internals.canvas.height },
|
|
3096
2866
|
visibilitySnapshots: frame.featureVisibilitySnapshots,
|
|
3097
2867
|
hiddenEntityReports: frame.hiddenEntityReports,
|
|
3098
2868
|
targets: featureTargets,
|
|
3099
2869
|
generation: internals.featureHost?.preparedGeneration ?? 0,
|
|
3100
2870
|
caps: internals.device.caps,
|
|
2871
|
+
frame: createCloudFeatureFrameContext(cloudLayer, featureView),
|
|
3101
2872
|
...(internals.getMaterialShaderBindingContract === undefined
|
|
3102
2873
|
? {}
|
|
3103
2874
|
: { materialShaderBindingContract: internals.getMaterialShaderBindingContract }),
|
|
@@ -3147,6 +2918,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3147
2918
|
featureGraphCandidate = {
|
|
3148
2919
|
plans: featureFrame.plans,
|
|
3149
2920
|
fullscreenEffects: featureFrame.fullscreenEffects,
|
|
2921
|
+
postProcessIdentities: featureFrame.postProcessIdentities,
|
|
3150
2922
|
...(featureFrame.requiresPreparedResourceKey
|
|
3151
2923
|
? { preparedResourceKey: `frame-${frameState.frameNumber}` }
|
|
3152
2924
|
: {}),
|
|
@@ -3288,11 +3060,44 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3288
3060
|
Number.isFinite(deltaTime) ? Math.max(0, deltaTime) : 0,
|
|
3289
3061
|
);
|
|
3290
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;
|
|
3291
3072
|
const probeCaptureScene =
|
|
3292
3073
|
shadowCasterProjection !== undefined &&
|
|
3293
3074
|
reflectionProbeRecord.graph.work.some((work) => work.rawCaptureFace !== undefined)
|
|
3294
3075
|
? projectCaptureScene(shadowCasterProjection, submissionRenderables, orderedDispatch)
|
|
3295
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
|
+
};
|
|
3296
3101
|
submitted = runProfiledRenderPhase(profileSession, 'record', () =>
|
|
3297
3102
|
recordFrame(
|
|
3298
3103
|
internals,
|
|
@@ -3325,6 +3130,15 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3325
3130
|
deviceGeneration: internals.deviceScope.generation,
|
|
3326
3131
|
},
|
|
3327
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 }),
|
|
3328
3142
|
},
|
|
3329
3143
|
compositionLeases,
|
|
3330
3144
|
featureGraphCandidate,
|
|
@@ -3351,13 +3165,16 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3351
3165
|
worldKeys,
|
|
3352
3166
|
undefined,
|
|
3353
3167
|
ssrDependencies,
|
|
3354
|
-
|
|
3168
|
+
markPresentedRenderable,
|
|
3355
3169
|
environment?.fog,
|
|
3356
3170
|
opts.sampleTimeSeconds,
|
|
3357
3171
|
opts.temporalReset === true,
|
|
3172
|
+
frame.cloudLayer,
|
|
3358
3173
|
),
|
|
3359
3174
|
);
|
|
3360
3175
|
dynamicGeometryFrames.commit(submitted);
|
|
3176
|
+
if (!submitted) surfaceSubmissionCandidate.abort();
|
|
3177
|
+
frameState.surfaceSubmissionObservation = undefined;
|
|
3361
3178
|
if (!submitted) discardLiveFeatureState();
|
|
3362
3179
|
if (submitted && lastLodOcclusionInspection !== undefined) {
|
|
3363
3180
|
const query = ensureOcclusionRuntime().inspect();
|
|
@@ -3381,6 +3198,111 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3381
3198
|
(frameState.currentDirectionalShadowView !== null &&
|
|
3382
3199
|
(lights.lightViewProj?.length ?? 0) > 0 &&
|
|
3383
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
|
+
}
|
|
3384
3306
|
if (submitted && directionalShadowReady) {
|
|
3385
3307
|
lastDirectionalShadowCandidate = 'accepted';
|
|
3386
3308
|
} else if (directionalQuality !== undefined) {
|
|
@@ -3398,6 +3320,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3398
3320
|
};
|
|
3399
3321
|
}
|
|
3400
3322
|
if (submitted) {
|
|
3323
|
+
lastPresentation = framePresentation;
|
|
3401
3324
|
recoveryOwner.setLastSuccessfulFrameSeed({
|
|
3402
3325
|
frame,
|
|
3403
3326
|
worlds: compositionWorlds,
|
|
@@ -3405,6 +3328,19 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3405
3328
|
resourceOwner: composition.owners.resourceOwner,
|
|
3406
3329
|
width: Math.max(1, internals.canvas.width),
|
|
3407
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 }),
|
|
3408
3344
|
});
|
|
3409
3345
|
submittedFrameCount += 1;
|
|
3410
3346
|
lastSubmittedGeneration = internals.deviceScope?.generation;
|
|
@@ -3418,13 +3354,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3418
3354
|
internals.errorRegistry.fire(temporalCommit.error);
|
|
3419
3355
|
}
|
|
3420
3356
|
frameState.lastSuccessfulCameraAntialias = cameras[0]?.antialias;
|
|
3421
|
-
const submittedCamera = cameras[0];
|
|
3422
3357
|
const submittedDepthOfField =
|
|
3423
|
-
|
|
3358
|
+
cameras[0] === undefined
|
|
3424
3359
|
? undefined
|
|
3425
3360
|
: resolveDepthOfFieldFrameParams(
|
|
3426
|
-
|
|
3427
|
-
|
|
3361
|
+
cameras[0].depthOfField,
|
|
3362
|
+
cameras[0].depthOfFieldError,
|
|
3428
3363
|
frameState.depthOfFieldAccepted?.params,
|
|
3429
3364
|
);
|
|
3430
3365
|
const submittedDepthOfFieldGraph = frameState.compiledFrameGraph?.inspect();
|
|
@@ -3521,6 +3456,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3521
3456
|
},
|
|
3522
3457
|
isDynamicGeometryConsumed: (world, entity, meshHandle) =>
|
|
3523
3458
|
dynamicGeometryFrames.isConsumed(world, entity, meshHandle),
|
|
3459
|
+
dynamicGeometryRecordStageLane: (world, entity, meshHandle) =>
|
|
3460
|
+
dynamicGeometryFrames.recordStageLane(world, entity, meshHandle),
|
|
3524
3461
|
pipelineDispatchCounts: dispatchCounts,
|
|
3525
3462
|
observeCurrentFrame(options: FrameObservationOptions) {
|
|
3526
3463
|
const currentFrameId = frameState.frameNumber - 1;
|
|
@@ -3557,6 +3494,20 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3557
3494
|
)
|
|
3558
3495
|
return;
|
|
3559
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
|
+
}
|
|
3560
3511
|
const published = lastLodOcclusionInspection;
|
|
3561
3512
|
if (
|
|
3562
3513
|
published !== undefined &&
|
|
@@ -3621,9 +3572,18 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3621
3572
|
get lastSuccessfulCameraAntialias(): CameraSnapshot['antialias'] | undefined {
|
|
3622
3573
|
return frameState.lastSuccessfulCameraAntialias;
|
|
3623
3574
|
},
|
|
3575
|
+
get lastSuccessfulBarrelDistortion(): BarrelDistortionMapping | undefined {
|
|
3576
|
+
return frameState.lastSuccessfulBarrelDistortion;
|
|
3577
|
+
},
|
|
3578
|
+
get barrelDistortionInspection(): BarrelDistortionInspection {
|
|
3579
|
+
return inspectBarrelDistortionState(frameState, internals.deviceScope?.generation ?? 0);
|
|
3580
|
+
},
|
|
3624
3581
|
get perFrameGraphInfo(): CompiledRenderGraphInfo | undefined {
|
|
3625
3582
|
return frameState.compiledFrameGraph?.inspect();
|
|
3626
3583
|
},
|
|
3584
|
+
get renderGraphGenerationAllocation() {
|
|
3585
|
+
return inspectRenderGraphGenerationAllocation(frameState);
|
|
3586
|
+
},
|
|
3627
3587
|
get featureGraphInspection(): import('./inspection-types').RenderFeatureGraphInspection {
|
|
3628
3588
|
return getRenderFeatureGraphInspection(internals);
|
|
3629
3589
|
},
|
|
@@ -3650,7 +3610,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3650
3610
|
});
|
|
3651
3611
|
},
|
|
3652
3612
|
get volumetricFog(): import('./volume/inspection').VolumetricFogInspection {
|
|
3653
|
-
|
|
3613
|
+
const accepted = frameState.volumetricFogAccepted;
|
|
3614
|
+
return {
|
|
3615
|
+
...frameState.volumetricFogInspection,
|
|
3616
|
+
ownerCount: accepted === undefined ? 0 : 1 + (accepted.additional?.length ?? 0),
|
|
3617
|
+
};
|
|
3654
3618
|
},
|
|
3655
3619
|
configureStandard(config: RenderPipelineAsset['config']): void {
|
|
3656
3620
|
const profileConfig = internals.standardProfile;
|
|
@@ -3729,7 +3693,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3729
3693
|
}
|
|
3730
3694
|
builtinPostProcessEntries.set(id, entry);
|
|
3731
3695
|
if (paramsBuffer !== undefined) postProcessParamsBuffers.set(id, paramsBuffer);
|
|
3732
|
-
const moduleLabel = postProcessShaderModuleLabel(
|
|
3696
|
+
const moduleLabel = postProcessShaderModuleLabel(entry.source);
|
|
3733
3697
|
return () => {
|
|
3734
3698
|
if (builtinPostProcessEntries.get(id) === entry) {
|
|
3735
3699
|
builtinPostProcessEntries.delete(id);
|
|
@@ -3778,6 +3742,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3778
3742
|
internals.getPipelineState()?.perPassResources.drainBloomResources?.();
|
|
3779
3743
|
internals.clearPostProcessPipelineCache?.('forgeax.taa-resolve');
|
|
3780
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);
|
|
3781
3750
|
resetHdrpBuffers(internals);
|
|
3782
3751
|
// Retire graph-owned resources and dispose instance-buffer caches.
|
|
3783
3752
|
// Both calls are idempotent + tolerate per-handle errors silently;
|
|
@@ -3789,6 +3758,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3789
3758
|
frameState.directionalShadowCacheRecorded = false;
|
|
3790
3759
|
frameState.currentFrameObservationSource = undefined;
|
|
3791
3760
|
frameState.lastSuccessfulCameraAntialias = undefined;
|
|
3761
|
+
frameState.lastSuccessfulBarrelDistortion = undefined;
|
|
3762
|
+
frameState.cloudHistoryActive = false;
|
|
3763
|
+
delete frameState.pendingCloudHistoryActive;
|
|
3792
3764
|
frameState.currentDirectionalShadowView = null;
|
|
3793
3765
|
frameState.currentSpotShadowView = null;
|
|
3794
3766
|
if (frameState.pendingAutoExposureGpuResources !== undefined) {
|
|
@@ -3816,6 +3788,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3816
3788
|
retireTemporalGpuState(retiring);
|
|
3817
3789
|
}
|
|
3818
3790
|
frameState.retiringTemporalGpuStates.clear();
|
|
3791
|
+
settleBarrelDistortionGraphCandidate(frameState, false);
|
|
3819
3792
|
settleVolumetricFogGraphCandidate(frameState, false);
|
|
3820
3793
|
for (const buffer of frameState.volumetricFogParamsBuffers) {
|
|
3821
3794
|
if (buffer === null) continue;
|
|
@@ -3849,9 +3822,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3849
3822
|
frameState.depthOfFieldCandidateGraph = null;
|
|
3850
3823
|
frameState.depthOfFieldAccepted = undefined;
|
|
3851
3824
|
frameState.depthOfFieldLastSubmitFailed = false;
|
|
3852
|
-
|
|
3825
|
+
resetBarrelDistortionGraphState(frameState);
|
|
3826
|
+
if (compiled !== null) retireCompiledGraph(frameState, compiled);
|
|
3853
3827
|
for (const retired of frameState.retiredCompiledFrameGraphs) {
|
|
3854
|
-
|
|
3828
|
+
retireCompiledGraph(frameState, retired);
|
|
3855
3829
|
}
|
|
3856
3830
|
frameState.retiredCompiledFrameGraphs.clear();
|
|
3857
3831
|
// feat-20260619 M4 (D-6): pass errorRegistry to disposeInstanceBuffers
|
|
@@ -3871,6 +3845,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3871
3845
|
}
|
|
3872
3846
|
frameState.probeBlendRecordBufferCapacity = 0;
|
|
3873
3847
|
frameState.probeBlendBuffers.clear();
|
|
3848
|
+
delete frameState.probeBlendRecordProjection;
|
|
3874
3849
|
if (frameState.morphBuffers !== undefined) {
|
|
3875
3850
|
for (const entry of frameState.morphBuffers.values()) {
|
|
3876
3851
|
if (!entry.buffer.isDestroyed) {
|
|
@@ -3909,6 +3884,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3909
3884
|
// device. Drop the shared Standard Cluster bundle before the next
|
|
3910
3885
|
// frame asks for a new generation; resetHdrpBuffers fences the bundle
|
|
3911
3886
|
// using its own device/queue instead of the replacement runtime device.
|
|
3887
|
+
resetSsaoResources(internals);
|
|
3912
3888
|
resetHdrpBuffers(internals);
|
|
3913
3889
|
// Keep the persistent material demand observable across device loss.
|
|
3914
3890
|
// The physical resource has already been fenced by markDeviceLost(); the
|
|
@@ -3949,9 +3925,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3949
3925
|
// must be discarded, not merely marked for destruction: their opaque
|
|
3950
3926
|
// handles cannot be used on the fresh device and the next draw must
|
|
3951
3927
|
// lazily build a new graph from the preserved ECS / asset POD caches.
|
|
3928
|
+
settleBarrelDistortionGraphCandidate(frameState, false);
|
|
3952
3929
|
settleVolumetricFogGraphCandidate(frameState, false);
|
|
3953
3930
|
settleDepthOfFieldGraphCandidate(frameState, false);
|
|
3954
|
-
frameState.compiledFrameGraph
|
|
3931
|
+
if (frameState.compiledFrameGraph !== null) {
|
|
3932
|
+
retireCompiledGraph(frameState, frameState.compiledFrameGraph);
|
|
3933
|
+
}
|
|
3955
3934
|
frameState.compiledFrameGraph = null;
|
|
3956
3935
|
frameState.compiledFrameGraphTopologyKey = null;
|
|
3957
3936
|
frameState.volumetricFogPreviousGraph = null;
|
|
@@ -3963,6 +3942,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3963
3942
|
frameState.depthOfFieldPreviousGraphGeneration = 0;
|
|
3964
3943
|
frameState.depthOfFieldPreviousStandardLightingGraphSignature = '';
|
|
3965
3944
|
frameState.depthOfFieldCandidateGraph = null;
|
|
3945
|
+
resetBarrelDistortionGraphState(frameState);
|
|
3966
3946
|
frameState.volumetricFogAccepted = undefined;
|
|
3967
3947
|
frameState.volumetricFogAcceptedContext = undefined;
|
|
3968
3948
|
frameState.volumetricFogHistoryGraph = null;
|
|
@@ -3989,6 +3969,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3989
3969
|
frameState.directionalShadowCacheRecorded = false;
|
|
3990
3970
|
frameState.currentFrameObservationSource = undefined;
|
|
3991
3971
|
frameState.lastSuccessfulCameraAntialias = undefined;
|
|
3972
|
+
frameState.lastSuccessfulBarrelDistortion = undefined;
|
|
3973
|
+
frameState.cloudHistoryActive = false;
|
|
3974
|
+
delete frameState.pendingCloudHistoryActive;
|
|
3992
3975
|
frameState.temporalFrameTransaction.reset('device-recovery');
|
|
3993
3976
|
frameState.temporalFrame = undefined;
|
|
3994
3977
|
frameState.temporalFrameInput = undefined;
|
|
@@ -4011,7 +3994,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
4011
3994
|
frameState.retiringTemporalGpuStates.clear();
|
|
4012
3995
|
frameState.hdrpClusterMembership = null;
|
|
4013
3996
|
for (const retired of frameState.retiredCompiledFrameGraphs) {
|
|
4014
|
-
|
|
3997
|
+
retireCompiledGraph(frameState, retired);
|
|
4015
3998
|
}
|
|
4016
3999
|
frameState.retiredCompiledFrameGraphs.clear();
|
|
4017
4000
|
frameState.instanceBuffers.clear();
|
|
@@ -4020,6 +4003,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
4020
4003
|
delete frameState.probeBlendRecordBuffer;
|
|
4021
4004
|
frameState.probeBlendRecordBufferCapacity = 0;
|
|
4022
4005
|
frameState.probeBlendBuffers.clear();
|
|
4006
|
+
delete frameState.probeBlendRecordProjection;
|
|
4023
4007
|
frameState.morphBuffers?.clear();
|
|
4024
4008
|
frameState.transientInstanceBuffers = [];
|
|
4025
4009
|
frameState.pointShadowAtlas = null;
|