@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
|
@@ -4,8 +4,11 @@ import {
|
|
|
4
4
|
type GraphResourceResolver,
|
|
5
5
|
RenderGraphBuilder,
|
|
6
6
|
RenderGraphError,
|
|
7
|
+
type RenderGraphGenerationAllocationEntry,
|
|
8
|
+
type RenderGraphGenerationAllocationInspection,
|
|
7
9
|
type RenderGraphPassInstrumentation,
|
|
8
10
|
type RenderGraphPassInstrumentationScope,
|
|
11
|
+
type RenderGraphResourceAllocationInspection,
|
|
9
12
|
} from '@forgeax/engine-render-graph';
|
|
10
13
|
import type {
|
|
11
14
|
BindGroup,
|
|
@@ -23,6 +26,7 @@ import { RhiError } from '@forgeax/engine-rhi';
|
|
|
23
26
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
24
27
|
import { executeRendererFrameTransaction } from '../assembly/renderer-frame-transaction';
|
|
25
28
|
import { standardBloomAdmitted } from '../bloom-admission';
|
|
29
|
+
import { CLOUD_LAYER_FEATURE_IDENTITY } from '../cloud/feature';
|
|
26
30
|
import { type RenderError, RenderFeatureStageFailedError } from '../errors/render';
|
|
27
31
|
import { depthOfFieldTopology } from '../features/depth-of-field/depth-of-field-feature';
|
|
28
32
|
import { resolveDepthOfFieldFrameParams } from '../features/depth-of-field/depth-of-field-params';
|
|
@@ -64,11 +68,7 @@ import {
|
|
|
64
68
|
} from '../gpu-texture-usage';
|
|
65
69
|
import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from '../gpu-usage';
|
|
66
70
|
import { createStandardSurfaceLightingBindGroup } from '../hdrp-buffers';
|
|
67
|
-
import type {
|
|
68
|
-
MotionBlurExecutionPass,
|
|
69
|
-
MotionBlurExecutionReceipt,
|
|
70
|
-
RenderFeatureGraphInspection,
|
|
71
|
-
} from '../inspection-types';
|
|
71
|
+
import type { RenderFeatureGraphInspection } from '../inspection-types';
|
|
72
72
|
import type { RenderExtent } from '../pipeline/render-extent';
|
|
73
73
|
import {
|
|
74
74
|
type StandardTopologyInputValue,
|
|
@@ -99,11 +99,13 @@ import type { RenderTarget } from '../targets/contracts';
|
|
|
99
99
|
import type { RenderTargetPhysical } from '../targets/physical';
|
|
100
100
|
import {
|
|
101
101
|
abortTemporalGpuSubmit,
|
|
102
|
+
CLOUD_HISTORY_FORMATS,
|
|
102
103
|
commitTemporalGpuSubmit,
|
|
103
104
|
getTemporalGpuState,
|
|
104
105
|
hasPendingTemporalGpuSubmit,
|
|
105
106
|
retireTemporalGpuState,
|
|
106
107
|
retireTemporalGpuStateAfterFence,
|
|
108
|
+
stageTemporalGpuSubmit,
|
|
107
109
|
TEMPORAL_HISTORY_FORMATS,
|
|
108
110
|
temporalReadIndex,
|
|
109
111
|
temporalWriteIndex,
|
|
@@ -124,6 +126,7 @@ import type { GpuPassTimingPassIdentity } from './gpu-pass-timing/contract.js';
|
|
|
124
126
|
import type { GpuPassTimingCapture, GpuPassTimingSession } from './gpu-pass-timing/session.js';
|
|
125
127
|
import type { GpuTimingCapture } from './gpu-timing';
|
|
126
128
|
import { encodeMainPass } from './main-pass';
|
|
129
|
+
import { deriveMotionBlurExecutionReceipt } from './motion-blur-receipt';
|
|
127
130
|
import type {
|
|
128
131
|
_InternalRenderPipelineContext,
|
|
129
132
|
PipelineState,
|
|
@@ -327,6 +330,125 @@ function importTemporalHistoryTargets(
|
|
|
327
330
|
};
|
|
328
331
|
}
|
|
329
332
|
|
|
333
|
+
type CloudHistoryKind = keyof typeof CLOUD_HISTORY_FORMATS;
|
|
334
|
+
|
|
335
|
+
function cloudHistorySurface(
|
|
336
|
+
state: import('../temporal/gpu').TemporalGpuState,
|
|
337
|
+
kind: CloudHistoryKind,
|
|
338
|
+
index: 0 | 1,
|
|
339
|
+
): { readonly texture: Texture; readonly view: TextureView } {
|
|
340
|
+
if (!state.cloudHistoryEnabled) {
|
|
341
|
+
throw new Error('cloud history target resolved without a cloud-enabled temporal state');
|
|
342
|
+
}
|
|
343
|
+
switch (kind) {
|
|
344
|
+
case 'radiance':
|
|
345
|
+
if (state.cloudRadiance === undefined)
|
|
346
|
+
throw new Error('cloud radiance history is unavailable');
|
|
347
|
+
return state.cloudRadiance[index];
|
|
348
|
+
case 'transmittance':
|
|
349
|
+
if (state.cloudTransmittance === undefined)
|
|
350
|
+
throw new Error('cloud transmittance history is unavailable');
|
|
351
|
+
return state.cloudTransmittance[index];
|
|
352
|
+
case 'depth':
|
|
353
|
+
if (state.cloudDepth === undefined) throw new Error('cloud depth history is unavailable');
|
|
354
|
+
return state.cloudDepth[index];
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/** Import one renderer-owned cloud history attachment into the typed graph. */
|
|
359
|
+
function importCloudHistoryTarget(
|
|
360
|
+
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
361
|
+
label: string,
|
|
362
|
+
kind: CloudHistoryKind,
|
|
363
|
+
role: 'read' | 'write',
|
|
364
|
+
): import('../render-pipeline').RenderPipelineTarget {
|
|
365
|
+
const format = CLOUD_HISTORY_FORMATS[kind];
|
|
366
|
+
const texture = graph.importTexture(
|
|
367
|
+
label,
|
|
368
|
+
{
|
|
369
|
+
format,
|
|
370
|
+
// Cloud transport/history is intentionally half-resolution. The
|
|
371
|
+
// renderer-owned temporal state allocates the same ceil(width/2) extent
|
|
372
|
+
// and the full-resolution resolve reconstructs scene colour from it.
|
|
373
|
+
size: 'half-surface',
|
|
374
|
+
usage:
|
|
375
|
+
GPU_TEXTURE_USAGE_COPY_SRC |
|
|
376
|
+
GPU_TEXTURE_USAGE_COPY_DST |
|
|
377
|
+
GPU_TEXTURE_USAGE_RENDER_ATTACHMENT |
|
|
378
|
+
GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
379
|
+
domain: 'linear-hdr',
|
|
380
|
+
},
|
|
381
|
+
(frame) => {
|
|
382
|
+
const internal = frame as _InternalRenderPipelineContext;
|
|
383
|
+
const state = getTemporalGpuState(
|
|
384
|
+
internal.frameState,
|
|
385
|
+
internal.runtime.device,
|
|
386
|
+
internal.runtime.deviceScope,
|
|
387
|
+
frame.targetW,
|
|
388
|
+
frame.targetH,
|
|
389
|
+
true,
|
|
390
|
+
);
|
|
391
|
+
const index = role === 'read' ? temporalReadIndex(state) : temporalWriteIndex(state);
|
|
392
|
+
return cloudHistorySurface(state, kind, index).texture;
|
|
393
|
+
},
|
|
394
|
+
);
|
|
395
|
+
if (!texture.ok) throw texture.error;
|
|
396
|
+
const view = graph.importView(
|
|
397
|
+
texture.value,
|
|
398
|
+
{ label: `${label}.view`, dimension: '2d' },
|
|
399
|
+
(frame) => {
|
|
400
|
+
const internal = frame as _InternalRenderPipelineContext;
|
|
401
|
+
const state = getTemporalGpuState(
|
|
402
|
+
internal.frameState,
|
|
403
|
+
internal.runtime.device,
|
|
404
|
+
internal.runtime.deviceScope,
|
|
405
|
+
frame.targetW,
|
|
406
|
+
frame.targetH,
|
|
407
|
+
true,
|
|
408
|
+
);
|
|
409
|
+
const index = role === 'read' ? temporalReadIndex(state) : temporalWriteIndex(state);
|
|
410
|
+
return cloudHistorySurface(state, kind, index).view;
|
|
411
|
+
},
|
|
412
|
+
);
|
|
413
|
+
if (!view.ok) throw view.error;
|
|
414
|
+
return { texture: texture.value, view: view.value, format, sampleCount: 1 };
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function importCloudHistoryTargets(
|
|
418
|
+
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
419
|
+
): NonNullable<
|
|
420
|
+
import('../render-pipeline').RenderPipelineBuildContext<RenderPipelineFrame>['cloudHistory']
|
|
421
|
+
> {
|
|
422
|
+
return {
|
|
423
|
+
currentRadiance: importCloudHistoryTarget(
|
|
424
|
+
graph,
|
|
425
|
+
'cloud-history-radiance-current',
|
|
426
|
+
'radiance',
|
|
427
|
+
'write',
|
|
428
|
+
),
|
|
429
|
+
previousRadiance: importCloudHistoryTarget(
|
|
430
|
+
graph,
|
|
431
|
+
'cloud-history-radiance-previous',
|
|
432
|
+
'radiance',
|
|
433
|
+
'read',
|
|
434
|
+
),
|
|
435
|
+
currentTransmittance: importCloudHistoryTarget(
|
|
436
|
+
graph,
|
|
437
|
+
'cloud-history-transmittance-current',
|
|
438
|
+
'transmittance',
|
|
439
|
+
'write',
|
|
440
|
+
),
|
|
441
|
+
previousTransmittance: importCloudHistoryTarget(
|
|
442
|
+
graph,
|
|
443
|
+
'cloud-history-transmittance-previous',
|
|
444
|
+
'transmittance',
|
|
445
|
+
'read',
|
|
446
|
+
),
|
|
447
|
+
currentDepth: importCloudHistoryTarget(graph, 'cloud-history-depth-current', 'depth', 'write'),
|
|
448
|
+
previousDepth: importCloudHistoryTarget(graph, 'cloud-history-depth-previous', 'depth', 'read'),
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
330
452
|
function importSsrHistoryTarget(
|
|
331
453
|
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
332
454
|
label: string,
|
|
@@ -982,6 +1104,7 @@ export interface RenderFeatureGraphRuntimeState {
|
|
|
982
1104
|
string,
|
|
983
1105
|
import('../fullscreen-post-process-pass').PostProcessShaderEntry
|
|
984
1106
|
>;
|
|
1107
|
+
postProcessIdentities: readonly string[];
|
|
985
1108
|
}
|
|
986
1109
|
|
|
987
1110
|
/** The exact fields that define one validated feature-plan collection. */
|
|
@@ -1042,6 +1165,8 @@ export interface RenderFeatureGraphCandidate {
|
|
|
1042
1165
|
string,
|
|
1043
1166
|
import('../fullscreen-post-process-pass').PostProcessShaderEntry
|
|
1044
1167
|
>;
|
|
1168
|
+
/** Public Standard post-effect identities; graph-local resources stay internal. */
|
|
1169
|
+
readonly postProcessIdentities?: readonly string[];
|
|
1045
1170
|
/**
|
|
1046
1171
|
* Physical transient graphics resources are imported into the compiled
|
|
1047
1172
|
* graph. Their lease therefore needs a new graph even when the declarative
|
|
@@ -1065,6 +1190,216 @@ export interface RenderFeatureGraphCandidate {
|
|
|
1065
1190
|
|
|
1066
1191
|
const featureGraphStates = new WeakMap<RenderSystemInternals, RenderFeatureGraphRuntimeState>();
|
|
1067
1192
|
const graphDeviceGenerations = new WeakMap<object, number>();
|
|
1193
|
+
const graphRetirementFailures = new WeakMap<
|
|
1194
|
+
RenderFrameState,
|
|
1195
|
+
Set<CompiledRenderGraph<RenderPipelineFrame>>
|
|
1196
|
+
>();
|
|
1197
|
+
|
|
1198
|
+
type GraphGenerationRole = 'active' | 'candidate' | 'retiring';
|
|
1199
|
+
type GraphGenerationStatus = 'active' | 'retiring' | 'failed' | 'retired';
|
|
1200
|
+
|
|
1201
|
+
interface GraphGenerationAllocationRecord {
|
|
1202
|
+
readonly graph: CompiledRenderGraph<RenderPipelineFrame>;
|
|
1203
|
+
status: GraphGenerationStatus;
|
|
1204
|
+
allocation: RenderGraphResourceAllocationInspection | undefined;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* One stable allocation owner for a RenderSystem lifetime. Recovery builds a
|
|
1209
|
+
* detached frame state, but that state intentionally shares this owner before
|
|
1210
|
+
* it can publish a candidate into the active RenderSystem. Graph records stay
|
|
1211
|
+
* here across asynchronous retirement so a successful replacement cannot
|
|
1212
|
+
* erase the overlap peak before the next public inspection.
|
|
1213
|
+
*/
|
|
1214
|
+
interface GraphGenerationAllocationOwner {
|
|
1215
|
+
readonly records: Map<CompiledRenderGraph<RenderPipelineFrame>, GraphGenerationAllocationRecord>;
|
|
1216
|
+
peakBytes: number;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
const graphGenerationAllocationOwners = new WeakMap<
|
|
1220
|
+
RenderFrameState,
|
|
1221
|
+
GraphGenerationAllocationOwner
|
|
1222
|
+
>();
|
|
1223
|
+
|
|
1224
|
+
function graphGenerationAllocationOwner(
|
|
1225
|
+
frameState: RenderFrameState,
|
|
1226
|
+
): GraphGenerationAllocationOwner {
|
|
1227
|
+
const existing = graphGenerationAllocationOwners.get(frameState);
|
|
1228
|
+
if (existing !== undefined) return existing;
|
|
1229
|
+
const created: GraphGenerationAllocationOwner = { records: new Map(), peakBytes: 0 };
|
|
1230
|
+
graphGenerationAllocationOwners.set(frameState, created);
|
|
1231
|
+
return created;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
function graphRetirementFailureSet(
|
|
1235
|
+
frameState: RenderFrameState,
|
|
1236
|
+
): Set<CompiledRenderGraph<RenderPipelineFrame>> {
|
|
1237
|
+
const existing = graphRetirementFailures.get(frameState);
|
|
1238
|
+
if (existing !== undefined) return existing;
|
|
1239
|
+
const created = new Set<CompiledRenderGraph<RenderPipelineFrame>>();
|
|
1240
|
+
graphRetirementFailures.set(frameState, created);
|
|
1241
|
+
return created;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/** Share the renderer-owned graph ledger with a detached recovery frame state. */
|
|
1245
|
+
export function shareRenderGraphGenerationAllocationOwner(
|
|
1246
|
+
source: RenderFrameState,
|
|
1247
|
+
target: RenderFrameState,
|
|
1248
|
+
): void {
|
|
1249
|
+
graphGenerationAllocationOwners.set(target, graphGenerationAllocationOwner(source));
|
|
1250
|
+
graphRetirementFailures.set(target, graphRetirementFailureSet(source));
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
function observeGraphGenerationAllocation(frameState: RenderFrameState): void {
|
|
1254
|
+
const owner = graphGenerationAllocationOwner(frameState);
|
|
1255
|
+
let simultaneousBytes = 0;
|
|
1256
|
+
for (const record of owner.records.values()) {
|
|
1257
|
+
if (record.status === 'retired') continue;
|
|
1258
|
+
const allocation = record.graph.inspect().resourceAllocation;
|
|
1259
|
+
record.allocation = allocation;
|
|
1260
|
+
if (allocation !== undefined) {
|
|
1261
|
+
simultaneousBytes += allocation.liveBytes + allocation.pendingRetirementBytes;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
owner.peakBytes = Math.max(owner.peakBytes, simultaneousBytes);
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
function trackGraphGeneration(
|
|
1268
|
+
frameState: RenderFrameState,
|
|
1269
|
+
graph: CompiledRenderGraph<RenderPipelineFrame>,
|
|
1270
|
+
): void {
|
|
1271
|
+
const owner = graphGenerationAllocationOwner(frameState);
|
|
1272
|
+
const record = owner.records.get(graph);
|
|
1273
|
+
if (record === undefined) {
|
|
1274
|
+
owner.records.set(graph, { graph, status: 'active', allocation: undefined });
|
|
1275
|
+
} else if (record.status === 'retired') {
|
|
1276
|
+
record.status = 'active';
|
|
1277
|
+
}
|
|
1278
|
+
observeGraphGenerationAllocation(frameState);
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
function setGraphGenerationRetiring(
|
|
1282
|
+
frameState: RenderFrameState,
|
|
1283
|
+
graph: CompiledRenderGraph<RenderPipelineFrame>,
|
|
1284
|
+
): void {
|
|
1285
|
+
const owner = graphGenerationAllocationOwner(frameState);
|
|
1286
|
+
const record = owner.records.get(graph);
|
|
1287
|
+
if (record === undefined) {
|
|
1288
|
+
owner.records.set(graph, { graph, status: 'retiring', allocation: undefined });
|
|
1289
|
+
} else if (record.status !== 'failed') {
|
|
1290
|
+
record.status = 'retiring';
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
function setGraphGenerationRetirementResult(
|
|
1295
|
+
frameState: RenderFrameState,
|
|
1296
|
+
graph: CompiledRenderGraph<RenderPipelineFrame>,
|
|
1297
|
+
succeeded: boolean,
|
|
1298
|
+
): void {
|
|
1299
|
+
const owner = graphGenerationAllocationOwner(frameState);
|
|
1300
|
+
const record = owner.records.get(graph);
|
|
1301
|
+
if (record !== undefined) record.status = succeeded ? 'retired' : 'failed';
|
|
1302
|
+
observeGraphGenerationAllocation(frameState);
|
|
1303
|
+
// A successful graph no longer owns any handles. Keep the renderer-level
|
|
1304
|
+
// peak scalar, but release the graph object from the generation map; failed
|
|
1305
|
+
// and pending owners remain retained for recovery inspection.
|
|
1306
|
+
if (succeeded) owner.records.delete(graph);
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
/**
|
|
1310
|
+
* Project the actual RenderSystem graph-generation owners as one detached
|
|
1311
|
+
* allocation receipt. The candidate and fallback graph can overlap before a
|
|
1312
|
+
* submit settles; failed retirement stays visible until the frame owner is
|
|
1313
|
+
* discarded instead of disappearing with the asynchronous Set entry.
|
|
1314
|
+
*/
|
|
1315
|
+
export function inspectRenderGraphGenerationAllocation(
|
|
1316
|
+
frameState: RenderFrameState,
|
|
1317
|
+
): RenderGraphGenerationAllocationInspection {
|
|
1318
|
+
const rolesByGraph = new Map<
|
|
1319
|
+
CompiledRenderGraph<RenderPipelineFrame>,
|
|
1320
|
+
Set<GraphGenerationRole>
|
|
1321
|
+
>();
|
|
1322
|
+
const add = (
|
|
1323
|
+
graph: CompiledRenderGraph<RenderPipelineFrame> | null | undefined,
|
|
1324
|
+
role: GraphGenerationRole,
|
|
1325
|
+
) => {
|
|
1326
|
+
if (graph === null || graph === undefined) return;
|
|
1327
|
+
const roles = rolesByGraph.get(graph);
|
|
1328
|
+
if (roles === undefined) rolesByGraph.set(graph, new Set([role]));
|
|
1329
|
+
else roles.add(role);
|
|
1330
|
+
};
|
|
1331
|
+
add(frameState.compiledFrameGraph, 'active');
|
|
1332
|
+
add(frameState.volumetricFogCandidateGraph, 'candidate');
|
|
1333
|
+
add(frameState.volumetricFogPreviousGraph, 'retiring');
|
|
1334
|
+
add(frameState.depthOfFieldCandidateGraph, 'candidate');
|
|
1335
|
+
add(frameState.depthOfFieldPreviousGraph, 'retiring');
|
|
1336
|
+
add(frameState.barrelDistortionCandidateGraph, 'candidate');
|
|
1337
|
+
add(frameState.barrelDistortionPreviousGraph, 'retiring');
|
|
1338
|
+
for (const graph of frameState.retiredCompiledFrameGraphs) add(graph, 'retiring');
|
|
1339
|
+
for (const graph of graphRetirementFailureSet(frameState)) add(graph, 'retiring');
|
|
1340
|
+
|
|
1341
|
+
const owner = graphGenerationAllocationOwner(frameState);
|
|
1342
|
+
const entries: RenderGraphGenerationAllocationEntry[] = [];
|
|
1343
|
+
let unavailableGenerationCount = 0;
|
|
1344
|
+
for (const [graph, record] of owner.records) {
|
|
1345
|
+
if (record.status === 'retired') continue;
|
|
1346
|
+
const roles = rolesByGraph.get(graph) ?? new Set<GraphGenerationRole>();
|
|
1347
|
+
if (record.status === 'retiring' || record.status === 'failed') roles.add('retiring');
|
|
1348
|
+
if (roles.size === 0) {
|
|
1349
|
+
// A candidate can be detached from the active state's role fields while
|
|
1350
|
+
// it is still being prepared. Keep its owner record observable until
|
|
1351
|
+
// the publication or cleanup event settles it.
|
|
1352
|
+
roles.add(record.status === 'active' ? 'active' : 'retiring');
|
|
1353
|
+
}
|
|
1354
|
+
// Inspection is a projection of the graph's current ledger. The cached
|
|
1355
|
+
// snapshot is only for event-time peak updates; using it here would make
|
|
1356
|
+
// a successfully fenced graph look live after its retirement started.
|
|
1357
|
+
const allocation = graph.inspect().resourceAllocation;
|
|
1358
|
+
record.allocation = allocation;
|
|
1359
|
+
if (allocation === undefined) {
|
|
1360
|
+
unavailableGenerationCount += 1;
|
|
1361
|
+
continue;
|
|
1362
|
+
}
|
|
1363
|
+
const retirement =
|
|
1364
|
+
record.status === 'failed' ? 'failed' : roles.has('retiring') ? 'pending' : 'active';
|
|
1365
|
+
entries.push({
|
|
1366
|
+
generation: graph.inspect().generation,
|
|
1367
|
+
roles: Object.freeze([...roles]),
|
|
1368
|
+
retirement,
|
|
1369
|
+
allocation,
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
entries.sort((left, right) => left.generation - right.generation);
|
|
1373
|
+
const liveBytes = entries.reduce((sum, entry) => sum + entry.allocation.liveBytes, 0);
|
|
1374
|
+
const pendingRetirementBytes = entries.reduce(
|
|
1375
|
+
(sum, entry) => sum + entry.allocation.pendingRetirementBytes,
|
|
1376
|
+
0,
|
|
1377
|
+
);
|
|
1378
|
+
const peakBytes = Math.max(owner.peakBytes, liveBytes + pendingRetirementBytes);
|
|
1379
|
+
const failedEntries = entries.filter((entry) => entry.retirement === 'failed');
|
|
1380
|
+
return Object.freeze({
|
|
1381
|
+
unit: 'engine-allocation-bytes',
|
|
1382
|
+
physicalResidency: 'unknown',
|
|
1383
|
+
availability:
|
|
1384
|
+
entries.length === 0
|
|
1385
|
+
? unavailableGenerationCount === 0
|
|
1386
|
+
? 'complete'
|
|
1387
|
+
: 'unavailable'
|
|
1388
|
+
: unavailableGenerationCount === 0
|
|
1389
|
+
? 'complete'
|
|
1390
|
+
: 'partial',
|
|
1391
|
+
unavailableGenerationCount,
|
|
1392
|
+
entries: Object.freeze(entries.map((entry) => Object.freeze(entry))),
|
|
1393
|
+
liveBytes,
|
|
1394
|
+
pendingRetirementBytes,
|
|
1395
|
+
peakBytes,
|
|
1396
|
+
failedRetirementCount: failedEntries.length,
|
|
1397
|
+
failedRetirementBytes: failedEntries.reduce(
|
|
1398
|
+
(sum, entry) => sum + entry.allocation.liveBytes + entry.allocation.pendingRetirementBytes,
|
|
1399
|
+
0,
|
|
1400
|
+
),
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1068
1403
|
|
|
1069
1404
|
interface MutableRenderFeatureGraphInspection {
|
|
1070
1405
|
planRevisionState: RenderFeaturePlanRevisionState;
|
|
@@ -1230,6 +1565,7 @@ export function getRenderFeatureGraphState(
|
|
|
1230
1565
|
const created: RenderFeatureGraphRuntimeState = {
|
|
1231
1566
|
plans: [],
|
|
1232
1567
|
fullscreenEffects: new Map(),
|
|
1568
|
+
postProcessIdentities: [],
|
|
1233
1569
|
};
|
|
1234
1570
|
featureGraphStates.set(internals, created);
|
|
1235
1571
|
return created;
|
|
@@ -1239,6 +1575,7 @@ export function resetRenderFeatureGraphState(internals: RenderSystemInternals):
|
|
|
1239
1575
|
const state = getRenderFeatureGraphState(internals);
|
|
1240
1576
|
state.plans = [];
|
|
1241
1577
|
state.fullscreenEffects = new Map();
|
|
1578
|
+
state.postProcessIdentities = [];
|
|
1242
1579
|
}
|
|
1243
1580
|
|
|
1244
1581
|
export function reportRenderFeatureGraphError(
|
|
@@ -1357,6 +1694,7 @@ function commitFeatureCandidate(
|
|
|
1357
1694
|
const state = getRenderFeatureGraphState(internals);
|
|
1358
1695
|
state.plans = candidate.plans;
|
|
1359
1696
|
state.fullscreenEffects = candidate.fullscreenEffects;
|
|
1697
|
+
state.postProcessIdentities = candidate.postProcessIdentities ?? [];
|
|
1360
1698
|
}
|
|
1361
1699
|
|
|
1362
1700
|
function topologyOf(
|
|
@@ -1378,6 +1716,7 @@ function topologyOf(
|
|
|
1378
1716
|
standardLighting: StandardTopologyInputValue | undefined,
|
|
1379
1717
|
ssr: SsrSpatialAdmission | undefined,
|
|
1380
1718
|
renderExtent: RenderExtent | undefined,
|
|
1719
|
+
surfaceMediumActive: boolean | undefined,
|
|
1381
1720
|
analyticFog: boolean,
|
|
1382
1721
|
): Result<RenderPipelineTopology, RhiError> {
|
|
1383
1722
|
const cascadeCount = Math.max(1, Math.min(4, Math.round(lights.cascadeCount ?? 1))) as
|
|
@@ -1399,10 +1738,9 @@ function topologyOf(
|
|
|
1399
1738
|
floatRenderAttachment: internals.device.caps.rgba16floatRenderable,
|
|
1400
1739
|
});
|
|
1401
1740
|
if (!surfaceProfile.ok) return surfaceProfile;
|
|
1402
|
-
const featurePostEffects =
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
].map(([id]) => id);
|
|
1741
|
+
const featurePostEffects =
|
|
1742
|
+
featureGraphCandidate?.postProcessIdentities ??
|
|
1743
|
+
getRenderFeatureGraphState(internals).postProcessIdentities;
|
|
1406
1744
|
const featurePostEffectDeclarations = [
|
|
1407
1745
|
...(featureGraphCandidate?.fullscreenEffects ??
|
|
1408
1746
|
getRenderFeatureGraphState(internals).fullscreenEffects),
|
|
@@ -1461,6 +1799,7 @@ function topologyOf(
|
|
|
1461
1799
|
// positive intensity changes update the recorder UBO in place.
|
|
1462
1800
|
bloom: standardBloomAdmitted(camera) ? 'on' : 'off',
|
|
1463
1801
|
bloomIntensity: camera.bloomIntensity,
|
|
1802
|
+
barrelDistortion: !clearOnly && (camera.barrelDistortion?.strength ?? 0) > 0,
|
|
1464
1803
|
...(depthOfField === undefined ? {} : { depthOfField }),
|
|
1465
1804
|
},
|
|
1466
1805
|
atmosphere: !clearOnly && frameState.environmentFrame?.source.kind === 'atmosphere',
|
|
@@ -1514,6 +1853,16 @@ function topologyOf(
|
|
|
1514
1853
|
return {
|
|
1515
1854
|
enabled: true,
|
|
1516
1855
|
format: volumetricFog.densityAsset.format,
|
|
1856
|
+
additional: (volumetricFog.additional ?? []).flatMap((member) =>
|
|
1857
|
+
member.densityAsset?.shape.viewDimension === '3d'
|
|
1858
|
+
? [
|
|
1859
|
+
{
|
|
1860
|
+
format: member.densityAsset.format,
|
|
1861
|
+
extent: member.densityAsset.shape.extent,
|
|
1862
|
+
},
|
|
1863
|
+
]
|
|
1864
|
+
: [],
|
|
1865
|
+
),
|
|
1517
1866
|
extent: {
|
|
1518
1867
|
width: volumetricFog.densityAsset.shape.extent.width,
|
|
1519
1868
|
height: volumetricFog.densityAsset.shape.extent.height,
|
|
@@ -1521,7 +1870,7 @@ function topologyOf(
|
|
|
1521
1870
|
},
|
|
1522
1871
|
froxelExtent: deriveVolumetricFogExtent(
|
|
1523
1872
|
{ width, height },
|
|
1524
|
-
volumeProfile.depth,
|
|
1873
|
+
volumeProfile.depth * (1 + (volumetricFog.additional?.length ?? 0)),
|
|
1525
1874
|
volumeProfile.tileSize,
|
|
1526
1875
|
),
|
|
1527
1876
|
resolvedExtent: deriveVolumetricFogResolvedExtent(
|
|
@@ -1562,6 +1911,9 @@ function topologyOf(
|
|
|
1562
1911
|
activeCount: 0,
|
|
1563
1912
|
needsRoughMips: false,
|
|
1564
1913
|
},
|
|
1914
|
+
...((surfaceMediumActive ?? gpuDriven?.surfaceSubmission !== undefined)
|
|
1915
|
+
? { singleLayerMedium: true }
|
|
1916
|
+
: {}),
|
|
1565
1917
|
});
|
|
1566
1918
|
}
|
|
1567
1919
|
|
|
@@ -1586,6 +1938,30 @@ function targetResolver(
|
|
|
1586
1938
|
...(named.resolveTarget === undefined ? {} : { resolveTarget: named.resolveTarget }),
|
|
1587
1939
|
};
|
|
1588
1940
|
}
|
|
1941
|
+
if (typeof resource === 'string') {
|
|
1942
|
+
const target = targets.find((candidate) => candidate.name === resource);
|
|
1943
|
+
if (target !== undefined) {
|
|
1944
|
+
return {
|
|
1945
|
+
texture: target.texture,
|
|
1946
|
+
view: target.view,
|
|
1947
|
+
...(target.resolveTarget === undefined ? {} : { resolveTarget: target.resolveTarget }),
|
|
1948
|
+
};
|
|
1949
|
+
}
|
|
1950
|
+
// Standard lanes expose the depth attachment as a semantic target
|
|
1951
|
+
// without duplicating the public `depth` name on every concrete graph
|
|
1952
|
+
// projection. Keep the string alias stable for feature-authored
|
|
1953
|
+
// fullscreen bindings while preserving the typed target identity.
|
|
1954
|
+
if (resource === 'depth') {
|
|
1955
|
+
const depth = targets.find((candidate) => candidate.kind === 'scene-depth');
|
|
1956
|
+
if (depth !== undefined) {
|
|
1957
|
+
return {
|
|
1958
|
+
texture: depth.texture,
|
|
1959
|
+
view: depth.view,
|
|
1960
|
+
...(depth.resolveTarget === undefined ? {} : { resolveTarget: depth.resolveTarget }),
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1589
1965
|
}
|
|
1590
1966
|
if (isSceneDataTarget(resource)) {
|
|
1591
1967
|
const semantic = semanticTargets.find(
|
|
@@ -1597,11 +1973,27 @@ function targetResolver(
|
|
|
1597
1973
|
: { texture: semantic.texture, view: semantic.view };
|
|
1598
1974
|
}
|
|
1599
1975
|
if (!isRenderFeatureTargetHandle(resource)) return undefined;
|
|
1976
|
+
// A typed feature handle is an identity, not a format request. Falling
|
|
1977
|
+
// back to another same-format target can silently bind scene color in
|
|
1978
|
+
// place of a missing cloud history/shadow resource and turn a producer
|
|
1979
|
+
// failure into plausible but incorrect pixels.
|
|
1980
|
+
// Standard lanes expose scene depth as a semantic target without a
|
|
1981
|
+
// duplicated public name, while feature plans use the stable `depth`
|
|
1982
|
+
// handle name. Preserve that one semantic alias here as well as above for
|
|
1983
|
+
// string-authored fullscreen bindings.
|
|
1600
1984
|
const target = targets.find(
|
|
1601
1985
|
(candidate) =>
|
|
1602
1986
|
candidate.kind === resource.kind &&
|
|
1603
1987
|
candidate.format === resource.format &&
|
|
1604
|
-
candidate.sampleCount === resource.sampleCount
|
|
1988
|
+
candidate.sampleCount === resource.sampleCount &&
|
|
1989
|
+
(resource.name === undefined ||
|
|
1990
|
+
candidate.name === resource.name ||
|
|
1991
|
+
(resource.kind === 'scene-color' &&
|
|
1992
|
+
resource.name === 'color' &&
|
|
1993
|
+
candidate.kind === 'scene-color') ||
|
|
1994
|
+
(resource.kind === 'scene-depth' &&
|
|
1995
|
+
resource.name === 'depth' &&
|
|
1996
|
+
candidate.kind === 'scene-depth')),
|
|
1605
1997
|
);
|
|
1606
1998
|
return target === undefined
|
|
1607
1999
|
? undefined
|
|
@@ -1621,6 +2013,9 @@ function resolveTargetBindings(
|
|
|
1621
2013
|
};
|
|
1622
2014
|
readonly resources: GraphResourceResolver;
|
|
1623
2015
|
readonly resolveTarget: RenderFeatureGraphTargetResolver;
|
|
2016
|
+
readonly resolveGpuResource?: (
|
|
2017
|
+
name: string,
|
|
2018
|
+
) => import('../features/prepared-gpu-work').RenderFeatureResolvedGpuBuffer | undefined;
|
|
1624
2019
|
},
|
|
1625
2020
|
featurePostProcessEntries?: ReadonlyMap<string, PostProcessShaderEntry>,
|
|
1626
2021
|
): RenderFeatureGraphBindingsResolution | undefined {
|
|
@@ -1632,6 +2027,136 @@ function resolveTargetBindings(
|
|
|
1632
2027
|
const sceneDepth = descriptor?.values.sceneDepth;
|
|
1633
2028
|
const sceneDepthBinding = descriptor?.values.sceneDepthBinding;
|
|
1634
2029
|
if (pipeline === undefined) return undefined;
|
|
2030
|
+
if (descriptor?.values.view === true) {
|
|
2031
|
+
const viewBindGroup = buildPerFrameBindGroups(
|
|
2032
|
+
frame.runtime as RenderSystemInternals,
|
|
2033
|
+
frame.frameState,
|
|
2034
|
+
frame.pipelineState,
|
|
2035
|
+
true,
|
|
2036
|
+
frame.bindGroupCounts,
|
|
2037
|
+
{
|
|
2038
|
+
directionalShadow: frame.frameState.currentDirectionalShadowView ?? undefined,
|
|
2039
|
+
spotShadow: frame.frameState.currentSpotShadowView ?? undefined,
|
|
2040
|
+
},
|
|
2041
|
+
true,
|
|
2042
|
+
frame.standardLighting,
|
|
2043
|
+
).viewBindGroup;
|
|
2044
|
+
return viewBindGroup === null ? undefined : { handle: viewBindGroup, dynamicOffsets: [0, 0] };
|
|
2045
|
+
}
|
|
2046
|
+
// Generic fullscreen producers (for example the CloudLayer scene pass)
|
|
2047
|
+
// share the renderer-owned post-process bind-group contract without opting
|
|
2048
|
+
// into the temporal two-input path below. Their input/depth aliases are
|
|
2049
|
+
// resolved from the active typed graph, so they cannot accidentally sample
|
|
2050
|
+
// a stale surface view or manufacture a second resource owner.
|
|
2051
|
+
if (descriptor?.values.fullscreen === true && !isTemporalFullscreenBinding(descriptor.values)) {
|
|
2052
|
+
const shader = descriptor.values.shader;
|
|
2053
|
+
if (typeof shader !== 'string') return undefined;
|
|
2054
|
+
const entry =
|
|
2055
|
+
featurePostProcessEntries?.get(shader) ?? frame.runtime.lookupPostProcess?.(shader);
|
|
2056
|
+
if (entry === undefined) return undefined;
|
|
2057
|
+
const depthFallback = descriptor.values.depthFallback === true;
|
|
2058
|
+
const depthValue = descriptor.values.depth;
|
|
2059
|
+
const depthTarget =
|
|
2060
|
+
depthFallback || depthValue === undefined
|
|
2061
|
+
? undefined
|
|
2062
|
+
: input.resolveTarget(depthValue as never);
|
|
2063
|
+
const fullscreen = buildFullscreenPostProcessPass(
|
|
2064
|
+
{ device: frame.runtime.device, errorRegistry: frame.runtime.errorRegistry },
|
|
2065
|
+
entry,
|
|
2066
|
+
depthTarget?.resolveTarget !== undefined,
|
|
2067
|
+
);
|
|
2068
|
+
if (fullscreen === null || fullscreen.sampler === null) return undefined;
|
|
2069
|
+
const inputDisabled = descriptor.values.input === false;
|
|
2070
|
+
const inputTarget = inputDisabled
|
|
2071
|
+
? undefined
|
|
2072
|
+
: input.resolveTarget(descriptor.values.input as never);
|
|
2073
|
+
const inputView =
|
|
2074
|
+
inputTarget === undefined
|
|
2075
|
+
? { ok: true as const, value: frame.pipelineState.defaultWhiteTextureView }
|
|
2076
|
+
: input.resources.textureView(inputTarget.view);
|
|
2077
|
+
if (!inputView.ok) return undefined;
|
|
2078
|
+
const depthView = depthFallback
|
|
2079
|
+
? frame.pipelineState.shadowFallbackTextureView
|
|
2080
|
+
: depthTarget === undefined
|
|
2081
|
+
? undefined
|
|
2082
|
+
: (() => {
|
|
2083
|
+
const depthTexture = input.resources.texture(depthTarget.texture);
|
|
2084
|
+
if (!depthTexture.ok) return undefined;
|
|
2085
|
+
const created = frame.runtime.device.createTextureView(depthTexture.value as Texture, {
|
|
2086
|
+
aspect: 'depth-only',
|
|
2087
|
+
dimension: '2d',
|
|
2088
|
+
});
|
|
2089
|
+
return created.ok ? created.value : undefined;
|
|
2090
|
+
})();
|
|
2091
|
+
if (
|
|
2092
|
+
depthTarget !== undefined &&
|
|
2093
|
+
(depthView === undefined || fullscreen.depthSampler === null)
|
|
2094
|
+
) {
|
|
2095
|
+
return undefined;
|
|
2096
|
+
}
|
|
2097
|
+
const additionalViews: { readonly binding: number; readonly view: TextureView }[] = [];
|
|
2098
|
+
const additionalNames = descriptor.values.additionalTextures;
|
|
2099
|
+
if (Array.isArray(additionalNames)) {
|
|
2100
|
+
for (const [index, value] of additionalNames.entries()) {
|
|
2101
|
+
if (typeof value !== 'string') return undefined;
|
|
2102
|
+
const target = input.resolveTarget(value);
|
|
2103
|
+
if (target === undefined) return undefined;
|
|
2104
|
+
const view = input.resources.textureView(target.view);
|
|
2105
|
+
if (!view.ok) return undefined;
|
|
2106
|
+
const binding = fullscreen.extraColorBindings[index];
|
|
2107
|
+
if (binding === undefined) return undefined;
|
|
2108
|
+
additionalViews.push({ binding, view: view.value });
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
const layout = pipeline.getBindGroupLayout?.(1);
|
|
2112
|
+
if (layout === undefined) return undefined;
|
|
2113
|
+
const paramsBuffer = frame.runtime.getPostProcessParamsBuffer?.(shader);
|
|
2114
|
+
if (entry.params !== undefined && paramsBuffer === undefined) return undefined;
|
|
2115
|
+
if (entry.params !== undefined && paramsBuffer !== undefined) {
|
|
2116
|
+
const data = frame.postProcessParams.get(shader) ?? entry.params.defaultValue;
|
|
2117
|
+
if (data.byteLength !== entry.params.byteSize) return undefined;
|
|
2118
|
+
const written = frame.runtime.device.queue.writeBuffer(paramsBuffer, 0, data);
|
|
2119
|
+
if (!written.ok) return undefined;
|
|
2120
|
+
}
|
|
2121
|
+
const createdBindGroup = createFullscreenBindGroup(
|
|
2122
|
+
frame.runtime.device,
|
|
2123
|
+
layout,
|
|
2124
|
+
inputView.value,
|
|
2125
|
+
fullscreen.sampler,
|
|
2126
|
+
paramsBuffer,
|
|
2127
|
+
depthView ?? null,
|
|
2128
|
+
fullscreen.depthSampler,
|
|
2129
|
+
additionalViews,
|
|
2130
|
+
fullscreen.extraStorageBindings.map((binding, index) => {
|
|
2131
|
+
const names = descriptor.values.storageBuffers;
|
|
2132
|
+
const name = Array.isArray(names) ? names[index] : undefined;
|
|
2133
|
+
if (typeof name !== 'string') throw new Error('fullscreen storage buffer name missing');
|
|
2134
|
+
const buffer = input.resolveGpuResource?.(name);
|
|
2135
|
+
if (buffer === undefined) throw new Error(`fullscreen storage buffer unavailable: ${name}`);
|
|
2136
|
+
return { binding, buffer: buffer.buffer };
|
|
2137
|
+
}),
|
|
2138
|
+
);
|
|
2139
|
+
if (createdBindGroup !== null) {
|
|
2140
|
+
// Cloud history is a producer of the shared temporal ping-pong state even
|
|
2141
|
+
// when TAA is disabled. Stage the write at encode time; execute's finish
|
|
2142
|
+
// guard and submit transaction then give it the same abort/commit/fence
|
|
2143
|
+
// semantics as the TAA resolve.
|
|
2144
|
+
if (shader === 'cloud-layer-resolve') {
|
|
2145
|
+
const state = getTemporalGpuState(
|
|
2146
|
+
frame.frameState,
|
|
2147
|
+
frame.runtime.device,
|
|
2148
|
+
frame.runtime.deviceScope,
|
|
2149
|
+
frame.targetW,
|
|
2150
|
+
frame.targetH,
|
|
2151
|
+
true,
|
|
2152
|
+
);
|
|
2153
|
+
stageTemporalGpuSubmit(state);
|
|
2154
|
+
frame.frameState.temporalGpuState = state;
|
|
2155
|
+
}
|
|
2156
|
+
return createdBindGroup;
|
|
2157
|
+
}
|
|
2158
|
+
return undefined;
|
|
2159
|
+
}
|
|
1635
2160
|
if (descriptor?.values.fullscreen === true && isTemporalFullscreenBinding(descriptor.values)) {
|
|
1636
2161
|
const shader = descriptor.values.shader;
|
|
1637
2162
|
if (typeof shader !== 'string') return undefined;
|
|
@@ -1646,11 +2171,9 @@ function resolveTargetBindings(
|
|
|
1646
2171
|
);
|
|
1647
2172
|
if (fullscreen === null || fullscreen.sampler === null) return undefined;
|
|
1648
2173
|
const inputTarget = input.resolveTarget(descriptor.values.input as never);
|
|
1649
|
-
|
|
1650
|
-
if (inputTarget === undefined || temporalTarget === undefined) return undefined;
|
|
2174
|
+
if (inputTarget === undefined) return undefined;
|
|
1651
2175
|
const inputView = input.resources.textureView(inputTarget.view);
|
|
1652
|
-
|
|
1653
|
-
if (!inputView.ok || !temporalView.ok) return undefined;
|
|
2176
|
+
if (!inputView.ok) return undefined;
|
|
1654
2177
|
const layout = pipeline.getBindGroupLayout?.(1);
|
|
1655
2178
|
if (layout === undefined) return undefined;
|
|
1656
2179
|
const depth = input.resolveTarget(descriptor.values.depth as never);
|
|
@@ -1669,13 +2192,41 @@ function resolveTargetBindings(
|
|
|
1669
2192
|
if (depth !== undefined && (depthView === undefined || fullscreen.depthSampler === null)) {
|
|
1670
2193
|
return undefined;
|
|
1671
2194
|
}
|
|
2195
|
+
|
|
2196
|
+
const paramsBuffer = frame.runtime.getPostProcessParamsBuffer?.(shader);
|
|
2197
|
+
if (entry.params !== undefined && paramsBuffer === undefined) return undefined;
|
|
2198
|
+
if (entry.params !== undefined && paramsBuffer !== undefined) {
|
|
2199
|
+
const data = frame.postProcessParams.get(shader) ?? entry.params.defaultValue;
|
|
2200
|
+
if (data.byteLength !== entry.params.byteSize) return undefined;
|
|
2201
|
+
const written = frame.runtime.device.queue.writeBuffer(paramsBuffer, 0, data);
|
|
2202
|
+
if (!written.ok) return undefined;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
if (!isTemporalFullscreenBinding(descriptor.values)) {
|
|
2206
|
+
return (
|
|
2207
|
+
createFullscreenBindGroup(
|
|
2208
|
+
frame.runtime.device,
|
|
2209
|
+
layout,
|
|
2210
|
+
inputView.value,
|
|
2211
|
+
fullscreen.sampler,
|
|
2212
|
+
paramsBuffer,
|
|
2213
|
+
depthView ?? null,
|
|
2214
|
+
fullscreen.depthSampler,
|
|
2215
|
+
) ?? undefined
|
|
2216
|
+
);
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
const temporalTarget = input.resolveTarget(descriptor.values.temporal as never);
|
|
2220
|
+
if (temporalTarget === undefined) return undefined;
|
|
2221
|
+
const temporalView = input.resources.textureView(temporalTarget.view);
|
|
2222
|
+
if (!temporalView.ok) return undefined;
|
|
1672
2223
|
return (
|
|
1673
2224
|
createFullscreenBindGroup(
|
|
1674
2225
|
frame.runtime.device,
|
|
1675
2226
|
layout,
|
|
1676
2227
|
inputView.value,
|
|
1677
2228
|
fullscreen.sampler,
|
|
1678
|
-
|
|
2229
|
+
paramsBuffer,
|
|
1679
2230
|
depthView ?? null,
|
|
1680
2231
|
fullscreen.depthSampler,
|
|
1681
2232
|
[{ binding: fullscreen.extraColorBindings[0] ?? 5, view: temporalView.value }],
|
|
@@ -1753,15 +2304,35 @@ function resolveTargetBindings(
|
|
|
1753
2304
|
return created.value;
|
|
1754
2305
|
}
|
|
1755
2306
|
|
|
1756
|
-
function retire(
|
|
2307
|
+
export function retire(
|
|
1757
2308
|
frameState: RenderFrameState,
|
|
1758
2309
|
graph: CompiledRenderGraph<RenderPipelineFrame>,
|
|
1759
2310
|
): void {
|
|
2311
|
+
if (frameState.retiredCompiledFrameGraphs.has(graph)) return;
|
|
1760
2312
|
frameState.retiredCompiledFrameGraphs.add(graph);
|
|
1761
|
-
graph
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
2313
|
+
setGraphGenerationRetiring(frameState, graph);
|
|
2314
|
+
const failures = graphRetirementFailureSet(frameState);
|
|
2315
|
+
const retirement = graph.retire();
|
|
2316
|
+
// retire() synchronously moves graph-owned resources to pending before its
|
|
2317
|
+
// queue-fence await. Capture that overlap at the lifecycle event, rather
|
|
2318
|
+
// than waiting for a later inspection call.
|
|
2319
|
+
observeGraphGenerationAllocation(frameState);
|
|
2320
|
+
retirement
|
|
2321
|
+
.then((result) => {
|
|
2322
|
+
if (result.ok) {
|
|
2323
|
+
failures?.delete(graph);
|
|
2324
|
+
setGraphGenerationRetirementResult(frameState, graph, true);
|
|
2325
|
+
} else {
|
|
2326
|
+
failures?.add(graph);
|
|
2327
|
+
setGraphGenerationRetirementResult(frameState, graph, false);
|
|
2328
|
+
}
|
|
2329
|
+
frameState.retiredCompiledFrameGraphs.delete(graph);
|
|
2330
|
+
})
|
|
2331
|
+
.catch(() => {
|
|
2332
|
+
failures?.add(graph);
|
|
2333
|
+
setGraphGenerationRetirementResult(frameState, graph, false);
|
|
2334
|
+
frameState.retiredCompiledFrameGraphs.delete(graph);
|
|
2335
|
+
});
|
|
1765
2336
|
}
|
|
1766
2337
|
|
|
1767
2338
|
/**
|
|
@@ -1838,6 +2409,54 @@ export function settleDepthOfFieldGraphCandidate(
|
|
|
1838
2409
|
frameState.depthOfFieldCandidateGraph = null;
|
|
1839
2410
|
}
|
|
1840
2411
|
|
|
2412
|
+
/**
|
|
2413
|
+
* Settle an ordinary graph replacement at the same submit barrier as the
|
|
2414
|
+
* barrel mapping. Resize, camera topology, and post-process enable/disable
|
|
2415
|
+
* all replace the compiled graph; a failed command must restore that graph so
|
|
2416
|
+
* the retained mapping still describes the pixels that are actually shown.
|
|
2417
|
+
*/
|
|
2418
|
+
export function settleBarrelDistortionGraphCandidate(
|
|
2419
|
+
frameState: RenderFrameState,
|
|
2420
|
+
submitted: boolean,
|
|
2421
|
+
): void {
|
|
2422
|
+
const candidate = frameState.barrelDistortionCandidateGraph ?? null;
|
|
2423
|
+
if (candidate === null) return;
|
|
2424
|
+
const previous = frameState.barrelDistortionPreviousGraph ?? null;
|
|
2425
|
+
const sharedWithSpecializedOwner =
|
|
2426
|
+
frameState.depthOfFieldCandidateGraph === candidate ||
|
|
2427
|
+
frameState.volumetricFogCandidateGraph === candidate;
|
|
2428
|
+
if (submitted) {
|
|
2429
|
+
if (!sharedWithSpecializedOwner && previous !== null && previous !== candidate) {
|
|
2430
|
+
retire(frameState, previous);
|
|
2431
|
+
}
|
|
2432
|
+
} else {
|
|
2433
|
+
if (!sharedWithSpecializedOwner) {
|
|
2434
|
+
if (candidate !== previous) retire(frameState, candidate);
|
|
2435
|
+
frameState.compiledFrameGraph = previous;
|
|
2436
|
+
frameState.compiledFrameGraphTopologyKey =
|
|
2437
|
+
frameState.barrelDistortionPreviousGraphKey ?? null;
|
|
2438
|
+
if (frameState.barrelDistortionPreviousPerFrameGraph === undefined) {
|
|
2439
|
+
delete frameState.perFrameGraph;
|
|
2440
|
+
} else {
|
|
2441
|
+
frameState.perFrameGraph = frameState.barrelDistortionPreviousPerFrameGraph;
|
|
2442
|
+
}
|
|
2443
|
+
frameState.graphGeneration = frameState.barrelDistortionPreviousGraphGeneration ?? 0;
|
|
2444
|
+
frameState.compiledFrameGraphGeneration =
|
|
2445
|
+
frameState.barrelDistortionPreviousCompiledGraphGeneration ?? 0;
|
|
2446
|
+
frameState.standardLightingGraphSignature =
|
|
2447
|
+
frameState.barrelDistortionPreviousStandardLightingGraphSignature ?? '';
|
|
2448
|
+
}
|
|
2449
|
+
frameState.barrelDistortionGraphResolution = previous === null ? 'accepted' : 'retained';
|
|
2450
|
+
}
|
|
2451
|
+
frameState.barrelDistortionPreviousGraph = null;
|
|
2452
|
+
frameState.barrelDistortionPreviousGraphKey = null;
|
|
2453
|
+
frameState.barrelDistortionPreviousPerFrameGraph = undefined;
|
|
2454
|
+
frameState.barrelDistortionPreviousGraphGeneration = 0;
|
|
2455
|
+
frameState.barrelDistortionPreviousCompiledGraphGeneration = 0;
|
|
2456
|
+
frameState.barrelDistortionPreviousStandardLightingGraphSignature = '';
|
|
2457
|
+
frameState.barrelDistortionCandidateGraph = null;
|
|
2458
|
+
}
|
|
2459
|
+
|
|
1841
2460
|
export function ensureCompiledFrameGraph(
|
|
1842
2461
|
internals: RenderSystemInternals,
|
|
1843
2462
|
frameState: RenderFrameState,
|
|
@@ -1859,8 +2478,11 @@ export function ensureCompiledFrameGraph(
|
|
|
1859
2478
|
onRecoveryError?: (error: unknown) => void,
|
|
1860
2479
|
ssr?: SsrSpatialAdmission,
|
|
1861
2480
|
renderExtent?: RenderExtent,
|
|
2481
|
+
surfaceMediumActive?: boolean,
|
|
1862
2482
|
analyticFog = false,
|
|
2483
|
+
cloudShadowResolution?: number,
|
|
1863
2484
|
): CompiledRenderGraph<RenderPipelineFrame> | null {
|
|
2485
|
+
frameState.barrelDistortionGraphResolution = 'retained';
|
|
1864
2486
|
const featureMetrics = mutableFeatureGraphInspection(internals);
|
|
1865
2487
|
featureMetrics.ensureCalls += 1;
|
|
1866
2488
|
const requestedStandardLightingSignature = standardLightingTopologySignature(standardLighting);
|
|
@@ -1878,10 +2500,16 @@ export function ensureCompiledFrameGraph(
|
|
|
1878
2500
|
: { ...camera, depthOfField: frameDepthOfField };
|
|
1879
2501
|
const lastKnownGood = (): CompiledRenderGraph<RenderPipelineFrame> | null =>
|
|
1880
2502
|
frameState.compiledFrameGraph !== null &&
|
|
2503
|
+
frameState.compiledFrameGraphTopologyKey !== null &&
|
|
1881
2504
|
!hasSubmissionSensitiveFeatures(getRenderFeatureGraphState(internals).plans) &&
|
|
1882
2505
|
frameState.standardLightingGraphSignature === requestedStandardLightingSignature
|
|
1883
2506
|
? frameState.compiledFrameGraph
|
|
1884
2507
|
: null;
|
|
2508
|
+
const retainLastKnownGood = (): CompiledRenderGraph<RenderPipelineFrame> | null => {
|
|
2509
|
+
const graph = lastKnownGood();
|
|
2510
|
+
if (graph !== null) frameState.barrelDistortionGraphResolution = 'retained';
|
|
2511
|
+
return graph;
|
|
2512
|
+
};
|
|
1885
2513
|
const surfaceWidth = Math.max(1, width);
|
|
1886
2514
|
const surfaceHeight = Math.max(1, height);
|
|
1887
2515
|
const featurePlans = featureGraphCandidate?.plans ?? getRenderFeatureGraphState(internals).plans;
|
|
@@ -1893,8 +2521,15 @@ export function ensureCompiledFrameGraph(
|
|
|
1893
2521
|
if (featureGraphCandidate !== undefined) {
|
|
1894
2522
|
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
1895
2523
|
}
|
|
1896
|
-
return volumeTopologyCandidate ? null :
|
|
2524
|
+
return volumeTopologyCandidate ? null : retainLastKnownGood();
|
|
1897
2525
|
}
|
|
2526
|
+
const cloudHistoryDemand = projectedFeaturePlans.value.some(
|
|
2527
|
+
(execution) =>
|
|
2528
|
+
execution.featureIdentity === CLOUD_LAYER_FEATURE_IDENTITY &&
|
|
2529
|
+
execution.passes.some(
|
|
2530
|
+
(pass) => pass.name === 'cloud-layer-transport' || pass.name === 'cloud-layer-resolve',
|
|
2531
|
+
),
|
|
2532
|
+
);
|
|
1898
2533
|
const nextPlanRevision = updateRenderFeaturePlanRevision(
|
|
1899
2534
|
featureMetrics.planRevisionState,
|
|
1900
2535
|
featurePlans,
|
|
@@ -1925,6 +2560,7 @@ export function ensureCompiledFrameGraph(
|
|
|
1925
2560
|
standardLighting,
|
|
1926
2561
|
ssr,
|
|
1927
2562
|
renderExtent,
|
|
2563
|
+
surfaceMediumActive,
|
|
1928
2564
|
analyticFog,
|
|
1929
2565
|
);
|
|
1930
2566
|
if (!topologyResult.ok) {
|
|
@@ -1934,7 +2570,7 @@ export function ensureCompiledFrameGraph(
|
|
|
1934
2570
|
if (featureGraphCandidate !== undefined) {
|
|
1935
2571
|
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
1936
2572
|
}
|
|
1937
|
-
return volumeTopologyCandidate ? null :
|
|
2573
|
+
return volumeTopologyCandidate ? null : retainLastKnownGood();
|
|
1938
2574
|
}
|
|
1939
2575
|
const requestedPostEffects = topologyResult.value.config?.postEffects ?? [];
|
|
1940
2576
|
const featurePostProcessEntries =
|
|
@@ -1986,6 +2622,7 @@ export function ensureCompiledFrameGraph(
|
|
|
1986
2622
|
if (featureGraphCandidate !== undefined) {
|
|
1987
2623
|
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
1988
2624
|
}
|
|
2625
|
+
frameState.barrelDistortionGraphResolution = 'retained';
|
|
1989
2626
|
return acceptedLkg;
|
|
1990
2627
|
}
|
|
1991
2628
|
const topology = postProcessAdmission.pending
|
|
@@ -2022,6 +2659,11 @@ export function ensureCompiledFrameGraph(
|
|
|
2022
2659
|
// so include the prepared projection's presence to invalidate a cached
|
|
2023
2660
|
// CPU-only graph when the GPU owner becomes ready, and vice versa.
|
|
2024
2661
|
gpuDrivenProjectionActive: gpuDriven !== undefined,
|
|
2662
|
+
// Cloud shadow targets are quality-derived graph resources. Include the
|
|
2663
|
+
// resolved texel grid in the cache key so a quality/resize change cannot
|
|
2664
|
+
// reuse a graph compiled for the previous allocation.
|
|
2665
|
+
cloudShadowResolution: cloudShadowResolution ?? 0,
|
|
2666
|
+
cloudHistory: cloudHistoryDemand,
|
|
2025
2667
|
// Query reservations are frame-local transport state. The projection is
|
|
2026
2668
|
// renderer-owned and read dynamically by the compiled pass, so a page
|
|
2027
2669
|
// rotation must not invalidate the graph or its cached bind groups.
|
|
@@ -2036,9 +2678,11 @@ export function ensureCompiledFrameGraph(
|
|
|
2036
2678
|
]),
|
|
2037
2679
|
});
|
|
2038
2680
|
if (frameState.compiledFrameGraph !== null && frameState.compiledFrameGraphTopologyKey === key) {
|
|
2681
|
+
frameState.barrelDistortionGraphResolution = 'accepted';
|
|
2039
2682
|
featureMetrics.reuseHits += 1;
|
|
2040
2683
|
featureMetrics.lastTopologyKey = key;
|
|
2041
2684
|
frameState.standardLightingGraphSignature = requestedStandardLightingSignature;
|
|
2685
|
+
frameState.pendingCloudHistoryActive = cloudHistoryDemand;
|
|
2042
2686
|
if (featureGraphCandidate !== undefined && !postProcessAdmission.pending) {
|
|
2043
2687
|
commitFeatureCandidate(internals, featureGraphCandidate);
|
|
2044
2688
|
} else if (featureGraphCandidate !== undefined) {
|
|
@@ -2068,9 +2712,11 @@ export function ensureCompiledFrameGraph(
|
|
|
2068
2712
|
topology.output?.autoExposure === true ? importAutoExposureGraphResources(builder) : undefined;
|
|
2069
2713
|
if (autoExposureResources !== undefined && !autoExposureResources.ok) {
|
|
2070
2714
|
internals.errorRegistry.fire(autoExposureResources.error);
|
|
2071
|
-
featureGraphCandidate?.onRejected?.();
|
|
2072
2715
|
discardPendingStandardOutput();
|
|
2073
|
-
|
|
2716
|
+
if (featureGraphCandidate !== undefined) {
|
|
2717
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
2718
|
+
}
|
|
2719
|
+
return retainLastKnownGood();
|
|
2074
2720
|
}
|
|
2075
2721
|
const lutResources =
|
|
2076
2722
|
topology.output?.colorLut === true
|
|
@@ -2114,20 +2760,25 @@ export function ensureCompiledFrameGraph(
|
|
|
2114
2760
|
: undefined;
|
|
2115
2761
|
if (lutResources !== undefined && !lutResources.ok) {
|
|
2116
2762
|
internals.errorRegistry.fire(lutResources.error);
|
|
2117
|
-
featureGraphCandidate?.onRejected?.();
|
|
2118
2763
|
discardPendingStandardOutput();
|
|
2119
|
-
|
|
2764
|
+
if (featureGraphCandidate !== undefined) {
|
|
2765
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
2766
|
+
}
|
|
2767
|
+
return retainLastKnownGood();
|
|
2120
2768
|
}
|
|
2121
2769
|
const taaHistory = camera.antialias === 'taa' ? importTemporalHistoryTargets(builder) : undefined;
|
|
2770
|
+
const cloudHistory = cloudHistoryDemand ? importCloudHistoryTargets(builder) : undefined;
|
|
2122
2771
|
const targetCoverage =
|
|
2123
2772
|
camera.dynamicResolution === undefined || topology.extent === undefined
|
|
2124
2773
|
? undefined
|
|
2125
2774
|
: createTargetCoverageAttachment(builder, topology.extent);
|
|
2126
2775
|
if (targetCoverage !== undefined && !targetCoverage.ok) {
|
|
2127
2776
|
internals.errorRegistry.fire(targetCoverage.error);
|
|
2128
|
-
featureGraphCandidate?.onRejected?.();
|
|
2129
2777
|
discardPendingStandardOutput();
|
|
2130
|
-
|
|
2778
|
+
if (featureGraphCandidate !== undefined) {
|
|
2779
|
+
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
2780
|
+
}
|
|
2781
|
+
return retainLastKnownGood();
|
|
2131
2782
|
}
|
|
2132
2783
|
const ssrHistory = ssr?.status === 'admitted' ? importSsrHistoryTargets(builder) : undefined;
|
|
2133
2784
|
const featureProjection = createRenderFeatureProjectionState();
|
|
@@ -2161,8 +2812,10 @@ export function ensureCompiledFrameGraph(
|
|
|
2161
2812
|
: {}),
|
|
2162
2813
|
...(standardLighting === undefined ? {} : { standardLighting }),
|
|
2163
2814
|
capabilities: { rgba16floatRenderable: internals.device.caps.rgba16floatRenderable },
|
|
2815
|
+
...(cloudShadowResolution === undefined ? {} : { cloudShadowResolution }),
|
|
2164
2816
|
...(occlusion === undefined ? {} : { occlusion }),
|
|
2165
2817
|
...(taaHistory === undefined ? {} : { taaHistory }),
|
|
2818
|
+
...(cloudHistory === undefined ? {} : { cloudHistory }),
|
|
2166
2819
|
...(targetCoverage?.ok === true ? { targetCoverage: targetCoverage.value } : {}),
|
|
2167
2820
|
...(ssrHistory === undefined ? {} : { ssrHistory }),
|
|
2168
2821
|
encodeTransmissionMip: ({ pass, resources, source }) => {
|
|
@@ -2178,6 +2831,7 @@ export function ensureCompiledFrameGraph(
|
|
|
2178
2831
|
builder,
|
|
2179
2832
|
target.format,
|
|
2180
2833
|
target.sampleCount,
|
|
2834
|
+
() => frameState.surfaceSubmissionObservation,
|
|
2181
2835
|
target.additionalColorFormats,
|
|
2182
2836
|
);
|
|
2183
2837
|
},
|
|
@@ -2198,23 +2852,42 @@ export function ensureCompiledFrameGraph(
|
|
|
2198
2852
|
semanticTargets = [],
|
|
2199
2853
|
namedTargets = {},
|
|
2200
2854
|
standardSurfaceAccesses = [],
|
|
2855
|
+
featureSelectionOrPlacement,
|
|
2856
|
+
passNames = [],
|
|
2201
2857
|
) => {
|
|
2202
|
-
|
|
2858
|
+
const selection =
|
|
2859
|
+
featureSelectionOrPlacement !== undefined &&
|
|
2860
|
+
typeof featureSelectionOrPlacement !== 'string'
|
|
2861
|
+
? featureSelectionOrPlacement
|
|
2862
|
+
: undefined;
|
|
2863
|
+
const placement =
|
|
2864
|
+
typeof featureSelectionOrPlacement === 'string' ? featureSelectionOrPlacement : 'post';
|
|
2865
|
+
const include = selection?.include === undefined ? undefined : new Set(selection.include);
|
|
2866
|
+
const exclude = selection?.exclude === undefined ? undefined : new Set(selection.exclude);
|
|
2867
|
+
// Forward/deferred scene lanes contribute scene plans before the
|
|
2203
2868
|
// Standard post chain has created its named input/output targets.
|
|
2204
2869
|
// Fullscreen effects (Motion Blur included) must wait for that later
|
|
2205
|
-
// call so their temporal input is resolved after TAA.
|
|
2206
|
-
//
|
|
2207
|
-
|
|
2870
|
+
// call so their temporal input is resolved after TAA. The shared
|
|
2871
|
+
// projection state below deduplicates only the execution/pass that
|
|
2872
|
+
// actually reached the graph; an empty early projection therefore
|
|
2873
|
+
// cannot reserve the later fullscreen pass.
|
|
2874
|
+
const plans = (
|
|
2208
2875
|
Object.keys(namedTargets).length === 0
|
|
2209
2876
|
? projectedFeaturePlans.value.filter(
|
|
2210
2877
|
(execution) => !fullscreenFeatureIds.has(execution.featureIdentity),
|
|
2211
2878
|
)
|
|
2212
|
-
: projectedFeaturePlans.value
|
|
2879
|
+
: projectedFeaturePlans.value
|
|
2880
|
+
)
|
|
2881
|
+
.filter((execution) => (execution.placement ?? 'post') === placement)
|
|
2882
|
+
.filter((execution) => include === undefined || include.has(execution.featureIdentity))
|
|
2883
|
+
.filter((execution) => exclude === undefined || !exclude.has(execution.featureIdentity));
|
|
2213
2884
|
if (plans.length === 0) return ok(undefined);
|
|
2214
2885
|
const resolveTarget = targetResolver(targets, semanticTargets, namedTargets);
|
|
2215
2886
|
const projected = projectPlanExecutions(builder, plans, {
|
|
2216
2887
|
state: featureProjection,
|
|
2217
2888
|
resolveTarget,
|
|
2889
|
+
placement,
|
|
2890
|
+
...(passNames.length === 0 ? {} : { passNames: new Set(passNames) }),
|
|
2218
2891
|
standardSurfaceAccesses,
|
|
2219
2892
|
resolveBindings: (input) => resolveTargetBindings(input, featurePostProcessEntries),
|
|
2220
2893
|
resolveStandardLighting: (frame, pipeline) => {
|
|
@@ -2239,7 +2912,8 @@ export function ensureCompiledFrameGraph(
|
|
|
2239
2912
|
},
|
|
2240
2913
|
reportError: (error) => reportRenderFeatureGraphError(internals, error),
|
|
2241
2914
|
});
|
|
2242
|
-
|
|
2915
|
+
if (!projected.ok) return projected;
|
|
2916
|
+
return ok(undefined);
|
|
2243
2917
|
},
|
|
2244
2918
|
contributeCubeCaptures: (environmentCube) => {
|
|
2245
2919
|
const reflectionProbes = addReflectionProbeGraphPasses(
|
|
@@ -2254,6 +2928,20 @@ export function ensureCompiledFrameGraph(
|
|
|
2254
2928
|
},
|
|
2255
2929
|
hasFeature: (identity) =>
|
|
2256
2930
|
projectedFeaturePlans.value.some((execution) => execution.featureIdentity === identity),
|
|
2931
|
+
hasFeatureWork: (identity, placement) =>
|
|
2932
|
+
projectedFeaturePlans.value.some(
|
|
2933
|
+
(execution) =>
|
|
2934
|
+
execution.featureIdentity === identity &&
|
|
2935
|
+
execution.passes.length > 0 &&
|
|
2936
|
+
(placement === undefined || (execution.placement ?? 'post') === placement),
|
|
2937
|
+
),
|
|
2938
|
+
hasFeatureRasterWork: (identity, placement) =>
|
|
2939
|
+
projectedFeaturePlans.value.some(
|
|
2940
|
+
(execution) =>
|
|
2941
|
+
execution.featureIdentity === identity &&
|
|
2942
|
+
execution.passes.some((pass) => pass.graphics !== undefined) &&
|
|
2943
|
+
(placement === undefined || (execution.placement ?? 'post') === placement),
|
|
2944
|
+
),
|
|
2257
2945
|
},
|
|
2258
2946
|
topology,
|
|
2259
2947
|
);
|
|
@@ -2261,12 +2949,11 @@ export function ensureCompiledFrameGraph(
|
|
|
2261
2949
|
featureMetrics.buildFailures += 1;
|
|
2262
2950
|
onRecoveryError?.(built.error);
|
|
2263
2951
|
internals.errorRegistry.fire(built.error);
|
|
2264
|
-
featureGraphCandidate?.onRejected?.();
|
|
2265
2952
|
discardPendingStandardOutput();
|
|
2266
2953
|
if (featureGraphCandidate !== undefined) {
|
|
2267
2954
|
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
2268
2955
|
}
|
|
2269
|
-
return volumeTopologyCandidate ? null :
|
|
2956
|
+
return volumeTopologyCandidate ? null : retainLastKnownGood();
|
|
2270
2957
|
}
|
|
2271
2958
|
featureMetrics.compileAttempts += 1;
|
|
2272
2959
|
const compileStarted = typeof performance === 'undefined' ? Date.now() : performance.now();
|
|
@@ -2280,13 +2967,16 @@ export function ensureCompiledFrameGraph(
|
|
|
2280
2967
|
featureMetrics.compileFailures += 1;
|
|
2281
2968
|
onRecoveryError?.(compiled.error);
|
|
2282
2969
|
internals.errorRegistry.fire(compiled.error);
|
|
2283
|
-
featureGraphCandidate?.onRejected?.();
|
|
2284
2970
|
discardPendingStandardOutput();
|
|
2285
2971
|
if (featureGraphCandidate !== undefined) {
|
|
2286
2972
|
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'rejected');
|
|
2287
2973
|
}
|
|
2288
|
-
return
|
|
2974
|
+
return retainLastKnownGood();
|
|
2289
2975
|
}
|
|
2976
|
+
// Register the generation before publishing it. The owner observes the
|
|
2977
|
+
// overlap while the previous graph is still live, even if a queue fence
|
|
2978
|
+
// retires that graph before the next public inspect() call.
|
|
2979
|
+
trackGraphGeneration(frameState, compiled.value);
|
|
2290
2980
|
const previous = frameState.compiledFrameGraph;
|
|
2291
2981
|
const depthOfFieldReplacement =
|
|
2292
2982
|
(frameState.depthOfFieldCandidateGraph === null ||
|
|
@@ -2314,8 +3004,22 @@ export function ensureCompiledFrameGraph(
|
|
|
2314
3004
|
frameState.depthOfFieldPreviousStandardLightingGraphSignature =
|
|
2315
3005
|
frameState.standardLightingGraphSignature;
|
|
2316
3006
|
frameState.depthOfFieldCandidateGraph = compiled.value;
|
|
3007
|
+
} else if (compiled.value !== previous) {
|
|
3008
|
+
// Keep the complete accepted graph projection until queue submission.
|
|
3009
|
+
// This covers barrel enable/disable, output resize, and camera topology
|
|
3010
|
+
// changes without introducing a second resource owner.
|
|
3011
|
+
frameState.barrelDistortionPreviousGraph = previous;
|
|
3012
|
+
frameState.barrelDistortionPreviousGraphKey = frameState.compiledFrameGraphTopologyKey;
|
|
3013
|
+
frameState.barrelDistortionPreviousPerFrameGraph = frameState.perFrameGraph;
|
|
3014
|
+
frameState.barrelDistortionPreviousGraphGeneration = frameState.graphGeneration;
|
|
3015
|
+
frameState.barrelDistortionPreviousCompiledGraphGeneration =
|
|
3016
|
+
frameState.compiledFrameGraphGeneration;
|
|
3017
|
+
frameState.barrelDistortionPreviousStandardLightingGraphSignature =
|
|
3018
|
+
frameState.standardLightingGraphSignature;
|
|
3019
|
+
frameState.barrelDistortionCandidateGraph = compiled.value;
|
|
2317
3020
|
}
|
|
2318
3021
|
frameState.compiledFrameGraph = compiled.value;
|
|
3022
|
+
frameState.barrelDistortionGraphResolution = 'accepted';
|
|
2319
3023
|
frameState.compiledFrameGraphTopologyKey = key;
|
|
2320
3024
|
frameState.standardLightingGraphSignature = requestedStandardLightingSignature;
|
|
2321
3025
|
frameState.compiledFrameGraphGeneration += 1;
|
|
@@ -2347,99 +3051,11 @@ export function ensureCompiledFrameGraph(
|
|
|
2347
3051
|
} else if (featureGraphCandidate !== undefined) {
|
|
2348
3052
|
recordRenderFeatureCandidateEvent(internals, featureGraphCandidate, 'abandoned');
|
|
2349
3053
|
}
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
}
|
|
3054
|
+
frameState.pendingCloudHistoryActive = cloudHistoryDemand;
|
|
3055
|
+
// The selected candidate owner retires the previous graph only after submit.
|
|
2353
3056
|
return compiled.value;
|
|
2354
3057
|
}
|
|
2355
3058
|
|
|
2356
|
-
/**
|
|
2357
|
-
* Project one accepted Motion Blur compute execution from the same graph and
|
|
2358
|
-
* resolved dispatch objects used by the encoder. A plan/capability candidate
|
|
2359
|
-
* without both executed passes deliberately returns no receipt.
|
|
2360
|
-
*/
|
|
2361
|
-
function deriveMotionBlurExecutionReceipt(
|
|
2362
|
-
internals: RenderSystemInternals,
|
|
2363
|
-
frameState: RenderFrameState,
|
|
2364
|
-
): MotionBlurExecutionReceipt | undefined {
|
|
2365
|
-
const graph = frameState.compiledFrameGraph;
|
|
2366
|
-
const deviceGeneration = internals.deviceScope?.generation;
|
|
2367
|
-
if (graph === null || deviceGeneration === undefined) return undefined;
|
|
2368
|
-
const info = graph.inspect();
|
|
2369
|
-
const graphPasses = new Map(info.passes.map((pass) => [pass.name, pass]));
|
|
2370
|
-
const summaryGraphPass = graphPasses.get('motion-blur-tile-summary');
|
|
2371
|
-
const reconstructGraphPass = graphPasses.get('motion-blur');
|
|
2372
|
-
if (summaryGraphPass?.kind !== 'compute' || reconstructGraphPass?.kind !== 'compute') {
|
|
2373
|
-
return undefined;
|
|
2374
|
-
}
|
|
2375
|
-
const planned = getRenderFeatureGraphState(internals).plans.find(
|
|
2376
|
-
(candidate) => candidate.featureIdentity === 'forgeax.motion-blur',
|
|
2377
|
-
);
|
|
2378
|
-
const execution =
|
|
2379
|
-
planned === undefined ? undefined : getRenderFeaturePlanExecutionProjection(planned);
|
|
2380
|
-
if (execution === undefined || execution.featureIdentity !== 'forgeax.motion-blur') {
|
|
2381
|
-
return undefined;
|
|
2382
|
-
}
|
|
2383
|
-
const executionPass = (name: 'motion-blur-tile-summary' | 'motion-blur') =>
|
|
2384
|
-
execution.passes.find((pass) => pass.name === name);
|
|
2385
|
-
const summary = executionPass('motion-blur-tile-summary');
|
|
2386
|
-
const reconstruct = executionPass('motion-blur');
|
|
2387
|
-
if (
|
|
2388
|
-
summary?.gpuCompute === undefined ||
|
|
2389
|
-
reconstruct?.gpuCompute === undefined ||
|
|
2390
|
-
summary.resolvedGpuCompute === undefined ||
|
|
2391
|
-
reconstruct.resolvedGpuCompute === undefined
|
|
2392
|
-
) {
|
|
2393
|
-
return undefined;
|
|
2394
|
-
}
|
|
2395
|
-
const directWorkgroups = (
|
|
2396
|
-
pass: NonNullable<typeof summary.resolvedGpuCompute>,
|
|
2397
|
-
): readonly [number, number, number] | undefined => {
|
|
2398
|
-
const dispatch = pass.dispatches[0];
|
|
2399
|
-
if (dispatch === undefined || !('workgroups' in dispatch)) return undefined;
|
|
2400
|
-
return dispatch.workgroups;
|
|
2401
|
-
};
|
|
2402
|
-
const summaryWorkgroups = directWorkgroups(summary.resolvedGpuCompute);
|
|
2403
|
-
const reconstructWorkgroups = directWorkgroups(reconstruct.resolvedGpuCompute);
|
|
2404
|
-
if (summaryWorkgroups === undefined || reconstructWorkgroups === undefined) return undefined;
|
|
2405
|
-
const outputResource = info.resources.find(
|
|
2406
|
-
(resource) =>
|
|
2407
|
-
resource.label === 'motion-blurred-color' ||
|
|
2408
|
-
reconstructGraphPass.accesses.some(
|
|
2409
|
-
(access) => access.resource === resource.label && access.usage === 'storage-write',
|
|
2410
|
-
),
|
|
2411
|
-
);
|
|
2412
|
-
if (
|
|
2413
|
-
outputResource?.descriptor.kind !== 'texture' ||
|
|
2414
|
-
outputResource.descriptor.format !== 'rgba16float'
|
|
2415
|
-
) {
|
|
2416
|
-
return undefined;
|
|
2417
|
-
}
|
|
2418
|
-
const summaryReceipt: MotionBlurExecutionPass = {
|
|
2419
|
-
name: 'motion-blur-tile-summary',
|
|
2420
|
-
kind: 'compute',
|
|
2421
|
-
entryPoint: 'tile_summary',
|
|
2422
|
-
workgroups: summaryWorkgroups,
|
|
2423
|
-
};
|
|
2424
|
-
const reconstructReceipt: MotionBlurExecutionPass = {
|
|
2425
|
-
name: 'motion-blur',
|
|
2426
|
-
kind: 'compute',
|
|
2427
|
-
entryPoint: 'reconstruct',
|
|
2428
|
-
workgroups: reconstructWorkgroups,
|
|
2429
|
-
};
|
|
2430
|
-
return Object.freeze({
|
|
2431
|
-
frameId: frameState.frameNumber,
|
|
2432
|
-
deviceGeneration,
|
|
2433
|
-
// RenderGraphBuilder generations are process-global. The renderer's
|
|
2434
|
-
// frame-state generation is the identity used by inspection and by the
|
|
2435
|
-
// same-frame admission check below, so retain that owner-scoped value.
|
|
2436
|
-
graphGeneration: frameState.graphGeneration,
|
|
2437
|
-
program: 'motion-blur-compute' as const,
|
|
2438
|
-
outputFormat: 'rgba16float' as const,
|
|
2439
|
-
passes: [summaryReceipt, reconstructReceipt] as const,
|
|
2440
|
-
});
|
|
2441
|
-
}
|
|
2442
|
-
|
|
2443
3059
|
export function executeCompiledFrameGraph(
|
|
2444
3060
|
internals: RenderSystemInternals,
|
|
2445
3061
|
frameState: RenderFrameState,
|
|
@@ -2462,21 +3078,31 @@ export function executeCompiledFrameGraph(
|
|
|
2462
3078
|
const legacySubmitCommit = typeof frameHooks === 'function' ? frameHooks : undefined;
|
|
2463
3079
|
const resolvedFrameHooks = typeof frameHooks === 'function' ? undefined : frameHooks;
|
|
2464
3080
|
const graph = frameState.compiledFrameGraph;
|
|
3081
|
+
// Recovery keeps the candidate graph for detached inspection, but clears
|
|
3082
|
+
// its topology key before the replacement canvas context is published. It
|
|
3083
|
+
// is evidence only until the first post-recovery draw compiles a new graph.
|
|
3084
|
+
// Never let that retained graph reach record/execute or queue.submit.
|
|
3085
|
+
const detachedGraph = graph !== null && frameState.compiledFrameGraphTopologyKey === null;
|
|
2465
3086
|
const rejectTemporalFrame = (): void => {
|
|
2466
3087
|
if (frameState.temporalFrameInput === undefined) return;
|
|
2467
3088
|
frameState.temporalFrameTransaction.commit({ accepted: false });
|
|
2468
3089
|
frameState.temporalFrameInput = undefined;
|
|
2469
3090
|
};
|
|
2470
|
-
if (graph === null) {
|
|
3091
|
+
if (graph === null || detachedGraph) {
|
|
2471
3092
|
timingCapture?.discard();
|
|
2472
3093
|
frameState.pendingAutoExposureState = undefined;
|
|
2473
3094
|
frameState.pendingStandardLutState = undefined;
|
|
3095
|
+
settleBarrelDistortionGraphCandidate(frameState, false);
|
|
2474
3096
|
settleVolumetricFogGraphCandidate(frameState, false);
|
|
2475
3097
|
settleDepthOfFieldGraphCandidate(frameState, false);
|
|
2476
3098
|
rejectTemporalFrame();
|
|
2477
3099
|
return false;
|
|
2478
3100
|
}
|
|
2479
|
-
const motionBlurExecution = deriveMotionBlurExecutionReceipt(
|
|
3101
|
+
const motionBlurExecution = deriveMotionBlurExecutionReceipt(
|
|
3102
|
+
internals,
|
|
3103
|
+
frameState,
|
|
3104
|
+
getRenderFeatureGraphState(internals).plans,
|
|
3105
|
+
);
|
|
2480
3106
|
const legacyTimingInstrumentation =
|
|
2481
3107
|
timingCapture === undefined ? undefined : createTimingInstrumentation(timingCapture);
|
|
2482
3108
|
const timingHost = internals as RenderSystemInternals & {
|
|
@@ -2539,6 +3165,7 @@ export function executeCompiledFrameGraph(
|
|
|
2539
3165
|
);
|
|
2540
3166
|
settleVolumetricFogGraphCandidate(frameState, false);
|
|
2541
3167
|
settleDepthOfFieldGraphCandidate(frameState, false);
|
|
3168
|
+
settleBarrelDistortionGraphCandidate(frameState, false);
|
|
2542
3169
|
return false;
|
|
2543
3170
|
}
|
|
2544
3171
|
const capturedGeneration = deviceScope?.generation;
|
|
@@ -3042,8 +3669,8 @@ export function executeCompiledFrameGraph(
|
|
|
3042
3669
|
internals.errorRegistry.fire(
|
|
3043
3670
|
new RhiError({
|
|
3044
3671
|
code: 'webgpu-runtime-error',
|
|
3045
|
-
expected: '
|
|
3046
|
-
hint: 'retry the frame after the
|
|
3672
|
+
expected: 'an admitted temporal producer stages a history write before submit',
|
|
3673
|
+
hint: 'retry the frame after the TAA or CloudLayer history pass has encoded successfully',
|
|
3047
3674
|
}),
|
|
3048
3675
|
);
|
|
3049
3676
|
return { ok: false, stage: 'finish' };
|
|
@@ -3197,6 +3824,11 @@ export function executeCompiledFrameGraph(
|
|
|
3197
3824
|
}
|
|
3198
3825
|
}
|
|
3199
3826
|
const stagedTemporalCommit = frameState.pendingTemporalCommit ?? { kind: 'none' as const };
|
|
3827
|
+
const stagedCloudHistoryActive = frameState.pendingCloudHistoryActive;
|
|
3828
|
+
if (stagedCloudHistoryActive !== undefined) {
|
|
3829
|
+
frameState.cloudHistoryActive = stagedCloudHistoryActive;
|
|
3830
|
+
delete frameState.pendingCloudHistoryActive;
|
|
3831
|
+
}
|
|
3200
3832
|
if (stagedTemporalCommit.kind !== 'none') {
|
|
3201
3833
|
frameState.lastSuccessfulTemporalView = stagedTemporalCommit.view;
|
|
3202
3834
|
}
|
|
@@ -3205,7 +3837,7 @@ export function executeCompiledFrameGraph(
|
|
|
3205
3837
|
} else if (stagedTemporalCommit.kind === 'off') {
|
|
3206
3838
|
frameState.successfulTemporalFrameIndex = 0;
|
|
3207
3839
|
}
|
|
3208
|
-
if (stagedTemporalCommit.kind === 'off') {
|
|
3840
|
+
if (stagedTemporalCommit.kind === 'off' && frameState.cloudHistoryActive !== true) {
|
|
3209
3841
|
internals.clearPostProcessPipelineCache?.('forgeax.taa-resolve');
|
|
3210
3842
|
// Retire frame-sized resources, not the device-owned prewarmed
|
|
3211
3843
|
// shader. The next TAA frame must not start an async cold compile.
|
|
@@ -3236,6 +3868,7 @@ export function executeCompiledFrameGraph(
|
|
|
3236
3868
|
frameState.pendingAtmospherePublish?.();
|
|
3237
3869
|
frameState.pendingAtmospherePublish = undefined;
|
|
3238
3870
|
onSubmitted?.(internals.device.queue.onSubmittedWorkDone());
|
|
3871
|
+
settleBarrelDistortionGraphCandidate(frameState, true);
|
|
3239
3872
|
settleVolumetricFogGraphCandidate(frameState, true);
|
|
3240
3873
|
settleDepthOfFieldGraphCandidate(frameState, true);
|
|
3241
3874
|
},
|
|
@@ -3271,11 +3904,13 @@ export function executeCompiledFrameGraph(
|
|
|
3271
3904
|
}
|
|
3272
3905
|
frameState.temporalGpuState = undefined;
|
|
3273
3906
|
}
|
|
3907
|
+
delete frameState.pendingCloudHistoryActive;
|
|
3274
3908
|
frameState.pendingTemporalCommit = { kind: 'none' };
|
|
3275
3909
|
if (frameState.environmentGeneration !== undefined) {
|
|
3276
3910
|
frameState.environmentLifecycle?.discard(frameState.environmentGeneration);
|
|
3277
3911
|
frameState.environmentGeneration = undefined;
|
|
3278
3912
|
}
|
|
3913
|
+
settleBarrelDistortionGraphCandidate(frameState, false);
|
|
3279
3914
|
settleVolumetricFogGraphCandidate(frameState, false);
|
|
3280
3915
|
settleDepthOfFieldGraphCandidate(frameState, false);
|
|
3281
3916
|
},
|
|
@@ -3283,6 +3918,7 @@ export function executeCompiledFrameGraph(
|
|
|
3283
3918
|
// The callbacks above settle the normal transaction path. Keep this guard
|
|
3284
3919
|
// for synthetic callers and any future early transaction result that does
|
|
3285
3920
|
// not enter a callback.
|
|
3921
|
+
settleBarrelDistortionGraphCandidate(frameState, transaction.ok);
|
|
3286
3922
|
settleVolumetricFogGraphCandidate(frameState, transaction.ok);
|
|
3287
3923
|
settleDepthOfFieldGraphCandidate(frameState, transaction.ok);
|
|
3288
3924
|
if (!transaction.ok) rejectTemporalFrame();
|