@forgeax/engine-render 0.1.32 → 0.1.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1374 -142
- package/dist/assembly/analytic-fog-registration.d.ts +3 -0
- package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
- package/dist/assembly/backend-contract.d.ts +2 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
- package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
- package/dist/assembly/canvas-draw-guard.d.ts +3 -0
- package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
- package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
- package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
- package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
- package/dist/assembly/factory.d.ts +1 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/fxaa-registration.d.ts +4 -0
- package/dist/assembly/fxaa-registration.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +3 -3
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/lod-observation.d.ts +4 -0
- package/dist/assembly/lod-observation.d.ts.map +1 -0
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
- package/dist/assembly/material-shader-policy.d.ts +16 -2
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
- package/dist/assembly/motion-blur-registration.d.ts +3 -0
- package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/render-feature-post-processes.d.ts +6 -0
- package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
- package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-inspection.d.ts +11 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -1
- package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
- package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
- package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
- package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +2 -2
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/barrel-distortion.d.ts +47 -0
- package/dist/barrel-distortion.d.ts.map +1 -0
- package/dist/bloom-admission.d.ts +13 -0
- package/dist/bloom-admission.d.ts.map +1 -0
- package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
- package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
- package/dist/{chunk-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
- package/dist/chunk-HEB564WF.mjs.map +1 -0
- package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
- package/dist/chunk-MKDIT2EM.mjs.map +1 -0
- package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
- package/dist/{chunk-S665NJNF.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
- package/dist/chunk-ODZWR6JQ.mjs +4927 -0
- package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
- package/dist/{chunk-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
- package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
- package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
- package/dist/chunk-UI5SFODX.mjs.map +1 -0
- package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
- package/dist/chunk-UINHLCZA.mjs.map +1 -0
- package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
- package/dist/chunk-WEX45HKH.mjs.map +1 -0
- package/dist/cloud/density.d.ts +55 -0
- package/dist/cloud/density.d.ts.map +1 -0
- package/dist/cloud/extract.d.ts +25 -0
- package/dist/cloud/extract.d.ts.map +1 -0
- package/dist/cloud/feature.d.ts +57 -0
- package/dist/cloud/feature.d.ts.map +1 -0
- package/dist/cloud/frame-context.d.ts +8 -0
- package/dist/cloud/frame-context.d.ts.map +1 -0
- package/dist/cloud/inspection.d.ts +59 -0
- package/dist/cloud/inspection.d.ts.map +1 -0
- package/dist/cloud/optics.d.ts +56 -0
- package/dist/cloud/optics.d.ts.map +1 -0
- package/dist/cloud/parameters.d.ts +73 -0
- package/dist/cloud/parameters.d.ts.map +1 -0
- package/dist/cloud/resources.d.ts +60 -0
- package/dist/cloud/resources.d.ts.map +1 -0
- package/dist/cloud/shadow.d.ts +42 -0
- package/dist/cloud/shadow.d.ts.map +1 -0
- package/dist/cloud/temporal.d.ts +74 -0
- package/dist/cloud/temporal.d.ts.map +1 -0
- package/dist/components/atmosphere.d.ts +2 -0
- package/dist/components/atmosphere.d.ts.map +1 -1
- package/dist/components/barrel-distortion.d.ts +13 -0
- package/dist/components/barrel-distortion.d.ts.map +1 -0
- package/dist/components/camera.d.ts +20 -4
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/cloud-layer.d.ts +29 -0
- package/dist/components/cloud-layer.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +20 -6
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/components/mesh-filter.d.ts +6 -5
- package/dist/components/mesh-filter.d.ts.map +1 -1
- package/dist/components/motion-blur.d.ts +1 -0
- package/dist/components/motion-blur.d.ts.map +1 -1
- package/dist/construct-renderer.d.ts +1 -1
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +9751 -3528
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +6 -0
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/dynamic-geometry.d.ts +5 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/environment/analytic-fog.d.ts +6 -0
- package/dist/environment/analytic-fog.d.ts.map +1 -0
- package/dist/errors/cloud.d.ts +59 -0
- package/dist/errors/cloud.d.ts.map +1 -0
- package/dist/errors/render.d.ts +23 -5
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/examples/single-layer-medium-surface.d.ts +47 -0
- package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +12 -1
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/environment.d.ts +2 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/features/barrel-distortion.d.ts +29 -0
- package/dist/features/barrel-distortion.d.ts.map +1 -0
- package/dist/features/error-reporting.d.ts +17 -0
- package/dist/features/error-reporting.d.ts.map +1 -0
- package/dist/features/host.d.ts +15 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
- package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
- package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
- package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
- package/dist/features/plan.d.ts +15 -4
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +9 -5
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/render-graph-compute.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +5 -0
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +1 -0
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/targets.d.ts +2 -0
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +44 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +15 -7
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-dirty-ranges.d.ts +11 -0
- package/dist/gpu-dirty-ranges.d.ts.map +1 -0
- package/dist/gpu-driven/batch-topology.d.ts +17 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts +6 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts +7 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster-material.d.ts +178 -0
- package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +50 -4
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/resource-allocation.d.ts +31 -0
- package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
- package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
- package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +35 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +11 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +2 -2
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +10 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +31 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +258 -8
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +178 -3
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instance-buffer-cache.d.ts +4 -4
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +49 -94
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +7 -7
- package/dist/pbr-pipeline.d.ts +19 -1
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
- package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
- package/dist/pipeline/standard-output/types.d.ts +4 -2
- package/dist/pipeline/standard-output/types.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +28 -19
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +2 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/record/barrel-distortion-frame.d.ts +15 -0
- package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
- package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
- package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
- package/dist/record/fold-buckets.d.ts +95 -0
- package/dist/record/fold-buckets.d.ts.map +1 -0
- package/dist/record/fold-instance-buffer.d.ts +6 -0
- package/dist/record/fold-instance-buffer.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +1 -0
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +40 -3
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +14 -62
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-draw-receipts.d.ts +11 -0
- package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +8 -0
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +21 -5
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +13 -2
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +6 -5
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/motion-blur-receipt.d.ts +11 -0
- package/dist/record/motion-blur-receipt.d.ts.map +1 -0
- package/dist/record/probe-blend-buffer.d.ts +16 -0
- package/dist/record/probe-blend-buffer.d.ts.map +1 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +34 -31
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -0
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +6 -4
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +22 -2
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +11 -3
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/record/volume-params.d.ts +9 -0
- package/dist/record/volume-params.d.ts.map +1 -0
- package/dist/recovery/render-system-candidate.d.ts +10 -0
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +66 -8
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +106 -3
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +3 -2
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +24 -10
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-presentation.d.ts +23 -0
- package/dist/render-system-presentation.d.ts.map +1 -0
- package/dist/render-system-producer-roots.d.ts +10 -0
- package/dist/render-system-producer-roots.d.ts.map +1 -0
- package/dist/render-system-residency.d.ts +12 -0
- package/dist/render-system-residency.d.ts.map +1 -0
- package/dist/render-system.d.ts +26 -15
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/probe-blend.d.ts +27 -0
- package/dist/scene/probe-blend.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +14 -5
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +9 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/surface/dynamic-input.d.ts +133 -0
- package/dist/surface/dynamic-input.d.ts.map +1 -0
- package/dist/surface/gpu-driven.d.ts +41 -0
- package/dist/surface/gpu-driven.d.ts.map +1 -0
- package/dist/surface/submission-observation.d.ts +136 -0
- package/dist/surface/submission-observation.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +7 -0
- package/dist/temporal/frame.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts +13 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- package/dist/temporal/inspection.d.ts.map +1 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
- package/dist/temporal/view.d.ts +6 -1
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/transmission/single-layer-medium.d.ts +89 -0
- package/dist/transmission/single-layer-medium.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +24 -9
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +9 -5
- package/dist/volume/component.d.ts.map +1 -1
- package/dist/volume/extract.d.ts +1 -1
- package/dist/volume/extract.d.ts.map +1 -1
- package/dist/volume/inspection.d.ts +2 -0
- package/dist/volume/inspection.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +4 -1
- package/dist/volume/passes.d.ts.map +1 -1
- package/dist/volume/resources.d.ts.map +1 -1
- package/dist/volume/temporal.d.ts +3 -1
- package/dist/volume/temporal.d.ts.map +1 -1
- package/package.json +22 -21
- package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
- package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
- package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
- package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
- package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
- package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
- package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
- package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
- package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
- package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
- package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
- package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
- package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
- package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
- package/src/__tests__/environment-selection.unit.test.ts +12 -0
- package/src/__tests__/factory-contract.integration.test.ts +626 -113
- package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
- package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
- package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
- package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +2 -1
- package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
- package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +7 -6
- package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
- package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
- package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
- package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
- package/src/__tests__/gpu-scene.unit.test.ts +210 -9
- package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
- package/src/__tests__/instances-culling.integration.test.ts +10 -36
- package/src/__tests__/instances-store.unit.test.ts +105 -238
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
- package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
- package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
- package/src/__tests__/motion-blur-compute.dawn.test.ts +589 -0
- package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
- package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
- package/src/__tests__/probe-bindings.unit.test.ts +582 -1
- package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
- package/src/__tests__/public-surface.test-d.ts +8 -0
- package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +9 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
- package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
- package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
- package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
- package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
- package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +37 -6
- package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
- package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
- package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +33 -11
- package/src/__tests__/resource-allocation.unit.test.ts +123 -0
- package/src/__tests__/shader-manifest-fixture.ts +4 -4
- package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
- package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +17 -0
- package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
- package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
- package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
- package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
- package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
- package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
- package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
- package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
- package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
- package/src/__tests__/temporal-performance.integration.test.ts +3 -3
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
- package/src/__tests__/temporal-view.unit.test.ts +2 -1
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
- package/src/__tests__/visibility-instances.integration.test.ts +7 -19
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
- package/src/__tests__/volume-optics-oracle.unit.test.ts +7 -3
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
- package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
- package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
- package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +558 -68
- package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
- package/src/assembly/analytic-fog-registration.ts +14 -0
- package/src/assembly/backend-contract.ts +30 -0
- package/src/assembly/barrel-distortion-inspection.ts +22 -0
- package/src/assembly/canvas-draw-guard.ts +11 -0
- package/src/assembly/cloud-shadow-entry.ts +22 -0
- package/src/assembly/dynamic-geometry-host.ts +65 -37
- package/src/assembly/dynamic-geometry-runtime.ts +7 -1
- package/src/assembly/factory.ts +2 -30
- package/src/assembly/fxaa-registration.ts +17 -0
- package/src/assembly/host-contract.ts +3 -3
- package/src/assembly/lod-observation.ts +12 -0
- package/src/assembly/material/assembly.ts +25 -13
- package/src/assembly/material/pipeline-helpers.ts +53 -12
- package/src/assembly/material-shader-policy.ts +55 -0
- package/src/assembly/material-shader-prewarm.ts +21 -10
- package/src/assembly/motion-blur-registration.ts +17 -0
- package/src/assembly/recovery/device-loss-fanout.ts +13 -0
- package/src/assembly/recovery/renderer-recover.ts +41 -18
- package/src/assembly/render-feature-post-processes.ts +54 -0
- package/src/assembly/renderer-facade.ts +6 -1
- package/src/assembly/renderer-feature-inspection.ts +8 -2
- package/src/assembly/renderer-frame-transaction.ts +23 -0
- package/src/assembly/renderer-inspection.ts +28 -0
- package/src/assembly/skin-palette-owner.ts +1 -1
- package/src/assembly/temporal-post-process-prewarm.ts +40 -0
- package/src/assembly/webgpu-pbr-ready.ts +9 -1
- package/src/assembly/webgpu-ready-contract.ts +8 -3
- package/src/assembly/webgpu-ready-per-pass.ts +104 -0
- package/src/assembly/webgpu-ready.ts +296 -306
- package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
- package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
- package/src/assembly/webgpu-renderer.ts +228 -281
- package/src/assembly/webgpu-vertex-layouts.ts +1 -1
- package/src/barrel-distortion.ts +247 -0
- package/src/bloom-admission.ts +21 -0
- package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
- package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
- package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
- package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
- package/src/cloud/density.ts +600 -0
- package/src/cloud/extract.ts +110 -0
- package/src/cloud/feature.ts +1810 -0
- package/src/cloud/frame-context.ts +42 -0
- package/src/cloud/inspection.ts +130 -0
- package/src/cloud/optics.ts +285 -0
- package/src/cloud/parameters.ts +255 -0
- package/src/cloud/resources.ts +122 -0
- package/src/cloud/shadow.ts +167 -0
- package/src/cloud/temporal.ts +226 -0
- package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
- package/src/components/atmosphere.ts +4 -0
- package/src/components/barrel-distortion.ts +46 -0
- package/src/components/camera.ts +66 -10
- package/src/components/cloud-layer.ts +47 -0
- package/src/components/index.ts +2 -0
- package/src/components/instances.ts +18 -45
- package/src/components/mesh-filter.ts +11 -9
- package/src/components/motion-blur.ts +1 -0
- package/src/components/sprite-instances.ts +1 -1
- package/src/construct-renderer.ts +1 -1
- package/src/device/gpu-residency.ts +56 -12
- package/src/dynamic-geometry.ts +12 -1
- package/src/environment/analytic-fog.ts +44 -0
- package/src/environment/background.ts +2 -2
- package/src/errors/cloud.ts +103 -0
- package/src/errors/render.ts +58 -8
- package/src/examples/single-layer-medium-surface.ts +59 -0
- package/src/extract/camera.ts +35 -8
- package/src/extract/contracts.ts +12 -0
- package/src/extract/environment.ts +4 -0
- package/src/features/barrel-distortion.ts +172 -0
- package/src/features/error-reporting.ts +98 -0
- package/src/features/host.ts +138 -24
- package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
- package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
- package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
- package/src/features/motion-blur/motion-blur-params.ts +70 -2
- package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
- package/src/features/plan.ts +33 -8
- package/src/features/prepared-gpu-work.ts +86 -35
- package/src/features/render-graph-compute.ts +13 -5
- package/src/features/render-graph-contribution.ts +11 -0
- package/src/features/render-graph-raster.ts +45 -3
- package/src/features/targets.ts +66 -0
- package/src/features/types.ts +47 -0
- package/src/fullscreen-post-process-pass.ts +41 -9
- package/src/gpu-dirty-ranges.ts +48 -0
- package/src/gpu-driven/batch-topology.ts +53 -0
- package/src/gpu-driven/material-artifacts.ts +35 -32
- package/src/gpu-driven/prepared-draw.ts +27 -14
- package/src/gpu-driven/production-raster-material.ts +1894 -0
- package/src/gpu-driven/production-raster.ts +904 -787
- package/src/gpu-driven/resource-allocation.ts +142 -0
- package/src/gpu-driven/shadow-ownership.ts +71 -0
- package/src/gpu-driven/view-gpu.ts +181 -10
- package/src/gpu-scene.ts +259 -101
- package/src/hdrp-buffers.ts +4 -3
- package/src/ibl/skylight-bind-group.ts +49 -7
- package/src/index.ts +228 -9
- package/src/inspection-types.ts +222 -2
- package/src/instance-buffer-cache.ts +4 -4
- package/src/instances.ts +151 -492
- package/src/pbr-pipeline.ts +219 -13
- package/src/pipeline/single-layer-medium-passes.ts +267 -0
- package/src/pipeline/standard-forward-lane.ts +313 -57
- package/src/pipeline/standard-output/graph.ts +8 -2
- package/src/pipeline/standard-output/types.ts +12 -1
- package/src/pipeline/standard-pipeline.ts +291 -18
- package/src/pipeline/standard-post.ts +397 -102
- package/src/pipeline-builder.ts +1 -1
- package/src/pipeline-spec.ts +5 -5
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
- package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
- package/src/prepare/prepared-graphics-resolver.ts +2 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
- package/src/record/__tests__/temporal-payload.unit.test.ts +3 -2
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
- package/src/record/barrel-distortion-frame.ts +110 -0
- package/src/record/dynamic-geometry-consumption.ts +39 -9
- package/src/record/fold-buckets.ts +852 -0
- package/src/record/fold-instance-buffer.ts +51 -0
- package/src/record/frame-lighting.ts +36 -2
- package/src/record/frame-snapshot.ts +44 -4
- package/src/record/frame-targets.ts +10 -6
- package/src/record/frame.ts +373 -1099
- package/src/record/gpu-draw-receipts.ts +38 -0
- package/src/record/gpu-timing.ts +48 -5
- package/src/record/main-pass-geometry.ts +281 -83
- package/src/record/main-pass-material.ts +66 -4
- package/src/record/main-pass-sprite-draws.ts +13 -66
- package/src/record/main-pass.ts +156 -20
- package/src/record/mesh-ssbo.ts +43 -6
- package/src/record/motion-blur-receipt.ts +91 -0
- package/src/record/probe-blend-buffer.ts +180 -0
- package/src/record/recovery-pipeline.ts +35 -3
- package/src/record/render-context.ts +51 -31
- package/src/record/shadow-pass.ts +36 -2
- package/src/record/skybox-post-pass.ts +150 -200
- package/src/record/typed-frame-graph.ts +824 -44
- package/src/record/view-ubo.ts +26 -3
- package/src/record/volume-params.ts +225 -0
- package/src/recovery/render-system-candidate.ts +257 -52
- package/src/reflection/record-owner.ts +7 -3
- package/src/render-contract.ts +71 -8
- package/src/render-graph-primitives.ts +7 -1
- package/src/render-pipeline.ts +136 -1
- package/src/render-system-extract-tail.ts +72 -60
- package/src/render-system-extract.ts +117 -87
- package/src/render-system-presentation.ts +56 -0
- package/src/render-system-producer-roots.ts +96 -0
- package/src/render-system-residency.ts +159 -0
- package/src/render-system.ts +601 -482
- package/src/scene/probe-blend.ts +96 -4
- package/src/scene/render-scene.ts +431 -281
- package/src/ssao-buffers.ts +95 -2
- package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
- package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
- package/src/surface/dynamic-input.ts +658 -0
- package/src/surface/gpu-driven.ts +147 -0
- package/src/surface/submission-observation.ts +517 -0
- package/src/systems/skin-palette-allocator.ts +4 -1
- package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
- package/src/temporal/frame-coordinator.ts +8 -1
- package/src/temporal/frame.ts +20 -0
- package/src/temporal/gpu.ts +101 -17
- package/src/temporal/inspection.ts +7 -1
- package/src/temporal/standard-scene-data.ts +5 -0
- package/src/temporal/target-coverage-attachment.ts +4 -0
- package/src/temporal/view.ts +13 -2
- package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
- package/src/transmission/single-layer-medium.ts +322 -0
- package/src/typed-render-graph-primitives.ts +191 -50
- package/src/volume/component.ts +10 -10
- package/src/volume/extract.ts +11 -5
- package/src/volume/inspection.ts +3 -0
- package/src/volume/passes.ts +95 -8
- package/src/volume/resources.ts +2 -1
- package/src/volume/temporal.ts +11 -0
- package/dist/chunk-4NNZQCL3.mjs.map +0 -1
- package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
- package/dist/chunk-DRR7D3KX.mjs.map +0 -1
- package/dist/chunk-GWCEMDVR.mjs.map +0 -1
- package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
- package/dist/chunk-JRIPCMYC.mjs.map +0 -1
- package/dist/chunk-LULCA3OF.mjs +0 -1713
- package/dist/chunk-LULCA3OF.mjs.map +0 -1
- package/dist/chunk-PA5DRJNI.mjs.map +0 -1
package/src/features/host.ts
CHANGED
|
@@ -17,7 +17,8 @@ import type {
|
|
|
17
17
|
PreparedGraphicsResolver,
|
|
18
18
|
PreparedGraphicsResourceLease,
|
|
19
19
|
} from '../prepare/prepared-graphics-resolver';
|
|
20
|
-
import type {
|
|
20
|
+
import type { CameraSnapshot } from '../render-contract';
|
|
21
|
+
import { isSceneDataTarget, type SceneDataTarget } from '../temporal/scene-data';
|
|
21
22
|
import { createSceneDataCatalog, type SceneDataCatalog } from '../temporal/scene-data-catalog';
|
|
22
23
|
import {
|
|
23
24
|
cloneRenderFeaturePlanSignatureSnapshot,
|
|
@@ -114,6 +115,7 @@ export interface RenderFeaturePlanExecutionPass {
|
|
|
114
115
|
export interface RenderFeaturePlanExecution {
|
|
115
116
|
readonly featureIdentity: string;
|
|
116
117
|
readonly order: number;
|
|
118
|
+
readonly placement?: import('./types').RenderFeaturePlacement;
|
|
117
119
|
readonly passes: readonly RenderFeaturePlanExecutionPass[];
|
|
118
120
|
}
|
|
119
121
|
|
|
@@ -134,6 +136,10 @@ export interface RenderFeatureFrameInput {
|
|
|
134
136
|
readonly worlds: readonly import('@forgeax/engine-ecs').World[];
|
|
135
137
|
readonly owner: number;
|
|
136
138
|
readonly frameNumber: number;
|
|
139
|
+
/** Renderer-selected display camera forwarded to feature extraction. */
|
|
140
|
+
readonly selectedCamera?: CameraSnapshot;
|
|
141
|
+
/** Physical render extent for bounded feature dispatch sizing. */
|
|
142
|
+
readonly frameSize?: { readonly width: number; readonly height: number };
|
|
137
143
|
readonly visibilitySnapshots?: readonly RenderFeatureWorldVisibilitySnapshot[];
|
|
138
144
|
readonly hiddenEntityReports?: readonly RenderFeatureHiddenEntityReport[];
|
|
139
145
|
/** Active-pipeline logical targets available to producer-owned features. */
|
|
@@ -142,6 +148,8 @@ export interface RenderFeatureFrameInput {
|
|
|
142
148
|
readonly sceneData?: SceneDataCatalog;
|
|
143
149
|
readonly generation?: number;
|
|
144
150
|
readonly caps: Readonly<RhiCaps>;
|
|
151
|
+
/** Normal frame-owner facts shared with producer extraction. */
|
|
152
|
+
readonly frame?: import('./types').RenderFeatureFrameContext;
|
|
145
153
|
/** Renderer-owned material binding contract projection for producer plans. */
|
|
146
154
|
readonly materialShaderBindingContract?: (
|
|
147
155
|
materialShaderId: string,
|
|
@@ -173,6 +181,8 @@ export interface RenderFeatureFrameResult {
|
|
|
173
181
|
readonly errors: readonly RenderError[];
|
|
174
182
|
readonly plans: readonly RenderFeaturePlannedFrame[];
|
|
175
183
|
readonly fullscreenEffects: ReadonlyMap<string, PostProcessShaderEntry>;
|
|
184
|
+
/** Public Standard post-effect identities; graph-local fullscreen resources are not included. */
|
|
185
|
+
readonly postProcessIdentities: readonly string[];
|
|
176
186
|
readonly preparedResourceBatches: readonly RenderFeaturePreparedResourceBatch[];
|
|
177
187
|
/**
|
|
178
188
|
* True only when the current graph resolves a transient graphics lease.
|
|
@@ -221,6 +231,8 @@ export interface RenderFeatureHost {
|
|
|
221
231
|
recover(input: RenderFeatureRecoverInput): Result<void, RenderError>;
|
|
222
232
|
createRecoveryRoot(scope: DeviceScope): LifecycleResourceSpec<unknown>;
|
|
223
233
|
diagnostics(): readonly RenderFeatureDiagnostics[];
|
|
234
|
+
/** Retain an explicitly producer-published detached inspection value. */
|
|
235
|
+
setInspection(identity: string, inspection: unknown): void;
|
|
224
236
|
/** Subscribe to lifecycle projection changes; unchanged active frames are silent. */
|
|
225
237
|
subscribeDiagnostics(listener: () => void): () => void;
|
|
226
238
|
/** Detached signature and prepared-resource accounting for diagnostics. */
|
|
@@ -267,6 +279,7 @@ interface FeatureSlot {
|
|
|
267
279
|
readonly preparedStore: PreparedGraphicsStore;
|
|
268
280
|
status: RenderFeatureStatus;
|
|
269
281
|
latestError: RenderFeatureErrorDescriptor | undefined;
|
|
282
|
+
latestInspection?: unknown;
|
|
270
283
|
}
|
|
271
284
|
|
|
272
285
|
function freezeError(error: RenderFeatureErrorDescriptor): RenderFeatureErrorDescriptor {
|
|
@@ -289,6 +302,7 @@ function freezeDiagnostics(slot: FeatureSlot): RenderFeatureDiagnostics {
|
|
|
289
302
|
order: slot.order,
|
|
290
303
|
status: slot.status,
|
|
291
304
|
latestError: slot.latestError === undefined ? undefined : freezeError(slot.latestError),
|
|
305
|
+
...(slot.latestInspection === undefined ? {} : { inspection: slot.latestInspection }),
|
|
292
306
|
});
|
|
293
307
|
}
|
|
294
308
|
|
|
@@ -318,6 +332,16 @@ function missingCapability(
|
|
|
318
332
|
return feature.requiredCapabilities?.find((capability) => caps[capability] !== true);
|
|
319
333
|
}
|
|
320
334
|
|
|
335
|
+
/**
|
|
336
|
+
* Capability declarations gate work that the current plan actually admits.
|
|
337
|
+
* A producer is still allowed to extract and return an empty plan when its
|
|
338
|
+
* authored feature is disabled; that path must remain allocation-free on a
|
|
339
|
+
* backend which cannot support the optional feature.
|
|
340
|
+
*/
|
|
341
|
+
function hasActivePlan(plan: RenderFeaturePlan): boolean {
|
|
342
|
+
return plan.resources.length > 0 || plan.passes.length > 0;
|
|
343
|
+
}
|
|
344
|
+
|
|
321
345
|
function createPreparedGraphicsPrepare(
|
|
322
346
|
transaction: PreparedGraphicsTransaction,
|
|
323
347
|
): RenderFeatureGraphicsPrepare {
|
|
@@ -344,6 +368,9 @@ function resolveGraphicsSnapshot(
|
|
|
344
368
|
resolver: PreparedGraphicsResolver,
|
|
345
369
|
descriptor: import('./prepared-graphics').RenderFeatureGraphicsPassDescriptor,
|
|
346
370
|
generation: number,
|
|
371
|
+
resolveGpuResource?: (
|
|
372
|
+
name: string,
|
|
373
|
+
) => import('./prepared-gpu-work').RenderFeatureResolvedGpuBuffer | undefined,
|
|
347
374
|
): Result<PreparedGraphicsResolvedSnapshot, RenderError> {
|
|
348
375
|
const resources = new Map<
|
|
349
376
|
object,
|
|
@@ -362,6 +389,7 @@ function resolveGraphicsSnapshot(
|
|
|
362
389
|
...(resolver.resolveGpuBuffer === undefined
|
|
363
390
|
? {}
|
|
364
391
|
: { resolveGpuBuffer: resolver.resolveGpuBuffer }),
|
|
392
|
+
...(resolveGpuResource === undefined ? {} : { resolveGpuResource }),
|
|
365
393
|
});
|
|
366
394
|
}
|
|
367
395
|
|
|
@@ -412,7 +440,7 @@ function asFeatureError(
|
|
|
412
440
|
if (error instanceof Error && typeof (error as Partial<RenderError>).code === 'string') {
|
|
413
441
|
return error as RenderError;
|
|
414
442
|
}
|
|
415
|
-
return new RenderFeatureStageFailedError(identity, order, stage, 'next-frame');
|
|
443
|
+
return new RenderFeatureStageFailedError(identity, order, stage, 'next-frame', error);
|
|
416
444
|
}
|
|
417
445
|
|
|
418
446
|
function featureErrorForSlot(slot: FeatureSlot, error: RenderError): RenderError {
|
|
@@ -431,6 +459,7 @@ function featureErrorForSlot(slot: FeatureSlot, error: RenderError): RenderError
|
|
|
431
459
|
slot.order,
|
|
432
460
|
'plan',
|
|
433
461
|
'next-frame',
|
|
462
|
+
error,
|
|
434
463
|
);
|
|
435
464
|
default:
|
|
436
465
|
return new RenderFeatureStageFailedError(
|
|
@@ -438,6 +467,7 @@ function featureErrorForSlot(slot: FeatureSlot, error: RenderError): RenderError
|
|
|
438
467
|
slot.order,
|
|
439
468
|
'plan',
|
|
440
469
|
'next-frame',
|
|
470
|
+
error,
|
|
441
471
|
);
|
|
442
472
|
}
|
|
443
473
|
}
|
|
@@ -467,6 +497,7 @@ function errorDescriptor(error: RenderError): RenderFeatureErrorDescriptor {
|
|
|
467
497
|
order: -1,
|
|
468
498
|
stage: 'plan',
|
|
469
499
|
recovery: 'next-frame',
|
|
500
|
+
cause: error,
|
|
470
501
|
},
|
|
471
502
|
};
|
|
472
503
|
}
|
|
@@ -606,14 +637,17 @@ function preparePlanResources(
|
|
|
606
637
|
: targetHandle(resource.logicalTarget, targets);
|
|
607
638
|
if (
|
|
608
639
|
resource.logicalTarget !== undefined &&
|
|
609
|
-
(logical === undefined ||
|
|
640
|
+
(logical === undefined ||
|
|
641
|
+
(typeof logical !== 'string' &&
|
|
642
|
+
!isRenderFeatureTargetHandle(logical) &&
|
|
643
|
+
!isSceneDataTarget(logical)))
|
|
610
644
|
) {
|
|
611
645
|
return err(planFailure(slot));
|
|
612
646
|
}
|
|
613
647
|
const prepared = gpu.prepareTextureView(
|
|
614
648
|
resource.name,
|
|
615
|
-
resource.resource.value as TextureView,
|
|
616
|
-
logical === undefined
|
|
649
|
+
resource.resource.value as TextureView | undefined,
|
|
650
|
+
logical === undefined ? undefined : logical,
|
|
617
651
|
);
|
|
618
652
|
if (!prepared.ok) return prepared;
|
|
619
653
|
preparedGpuResources.set(resource.name, {
|
|
@@ -963,6 +997,7 @@ function projectPlanPasses(
|
|
|
963
997
|
return ok({
|
|
964
998
|
featureIdentity: slot.feature.identity,
|
|
965
999
|
order: slot.order,
|
|
1000
|
+
...(slot.feature.placement === undefined ? {} : { placement: slot.feature.placement }),
|
|
966
1001
|
passes: Object.freeze(projected),
|
|
967
1002
|
});
|
|
968
1003
|
}
|
|
@@ -1322,6 +1357,13 @@ class FeatureHostImpl implements RenderFeatureHost {
|
|
|
1322
1357
|
return Object.freeze(this.slots.map(freezeDiagnostics));
|
|
1323
1358
|
}
|
|
1324
1359
|
|
|
1360
|
+
/** Retain only an explicitly producer-published detached inspection value. */
|
|
1361
|
+
setInspection(identity: string, inspection: unknown): void {
|
|
1362
|
+
const slot = findSlot(this.slots, identity);
|
|
1363
|
+
if (slot === undefined || slot.status === 'disposed') return;
|
|
1364
|
+
slot.latestInspection = inspection;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1325
1367
|
subscribeDiagnostics(listener: () => void): () => void {
|
|
1326
1368
|
this.diagnosticsListeners.add(listener);
|
|
1327
1369
|
return () => this.diagnosticsListeners.delete(listener);
|
|
@@ -1352,6 +1394,7 @@ export function runRenderFeatureFrame(
|
|
|
1352
1394
|
const errors: RenderError[] = [];
|
|
1353
1395
|
const plans: RenderFeaturePlannedFrame[] = [];
|
|
1354
1396
|
const fullscreenEffects = new Map<string, PostProcessShaderEntry>();
|
|
1397
|
+
const postProcessIdentities = new Set<string>();
|
|
1355
1398
|
const preparedResourceBatches: RenderFeaturePreparedResourceBatch[] = [];
|
|
1356
1399
|
let requiresPreparedResourceKey = false;
|
|
1357
1400
|
const hiddenEntityReports: RenderFeatureHiddenEntityReport[] = [
|
|
@@ -1362,17 +1405,18 @@ export function runRenderFeatureFrame(
|
|
|
1362
1405
|
const diagnostics = host.diagnostics();
|
|
1363
1406
|
for (const [order, feature] of host.features.entries()) {
|
|
1364
1407
|
const diagnostic = diagnostics[order];
|
|
1365
|
-
if (diagnostic?.status === '
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1408
|
+
if (diagnostic?.status === 'disposed') continue;
|
|
1409
|
+
// Preserve the existing recovery contract for a capability-disabled
|
|
1410
|
+
// feature once the device becomes capable: an explicit host.recover()
|
|
1411
|
+
// still re-admits it. While the capability is absent, however, rerun the
|
|
1412
|
+
// producer so a camera/world can disable its authored plan and recover to
|
|
1413
|
+
// an empty, zero-resource frame without a second manager.
|
|
1414
|
+
if (diagnostic?.status === 'disabled') {
|
|
1415
|
+
const diagnosticError = diagnostic.latestError;
|
|
1416
|
+
const missing = missingCapability(feature, input.caps);
|
|
1417
|
+
if (diagnosticError?.code !== 'render-feature-capability-missing' || missing === undefined) {
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1376
1420
|
}
|
|
1377
1421
|
const slot: FeatureSlot = {
|
|
1378
1422
|
feature,
|
|
@@ -1383,6 +1427,9 @@ export function runRenderFeatureFrame(
|
|
|
1383
1427
|
latestError: undefined,
|
|
1384
1428
|
};
|
|
1385
1429
|
const identity = slot.feature.identity;
|
|
1430
|
+
for (const postProcess of feature.requiredFullscreenPostProcesses ?? []) {
|
|
1431
|
+
postProcessIdentities.add(postProcess.identity);
|
|
1432
|
+
}
|
|
1386
1433
|
const transaction = host.beginPreparedFrame(identity, input.generation ?? 0);
|
|
1387
1434
|
if (transaction === undefined) continue;
|
|
1388
1435
|
const graphics = createPreparedGraphicsPrepare(transaction);
|
|
@@ -1396,6 +1443,9 @@ export function runRenderFeatureFrame(
|
|
|
1396
1443
|
worlds: input.worlds,
|
|
1397
1444
|
owner: input.owner,
|
|
1398
1445
|
frameNumber: input.frameNumber,
|
|
1446
|
+
...(input.selectedCamera === undefined ? {} : { selectedCamera: input.selectedCamera }),
|
|
1447
|
+
caps: input.caps,
|
|
1448
|
+
...(input.frame === undefined ? {} : { frame: input.frame }),
|
|
1399
1449
|
reportHiddenEntity: (report) => featureHiddenEntityReports.push(report),
|
|
1400
1450
|
...(input.visibilitySnapshots === undefined
|
|
1401
1451
|
? {}
|
|
@@ -1413,6 +1463,16 @@ export function runRenderFeatureFrame(
|
|
|
1413
1463
|
host.setStatus(identity, 'failed', slot.latestError);
|
|
1414
1464
|
continue;
|
|
1415
1465
|
}
|
|
1466
|
+
if (
|
|
1467
|
+
typeof extracted.value === 'object' &&
|
|
1468
|
+
extracted.value !== null &&
|
|
1469
|
+
'inspection' in extracted.value
|
|
1470
|
+
) {
|
|
1471
|
+
host.setInspection(
|
|
1472
|
+
identity,
|
|
1473
|
+
(extracted.value as { readonly inspection?: unknown }).inspection,
|
|
1474
|
+
);
|
|
1475
|
+
}
|
|
1416
1476
|
|
|
1417
1477
|
const targets = logicalTargets(input.targets ?? []);
|
|
1418
1478
|
const sceneData =
|
|
@@ -1429,7 +1489,10 @@ export function runRenderFeatureFrame(
|
|
|
1429
1489
|
() =>
|
|
1430
1490
|
feature.plan(extracted.value, {
|
|
1431
1491
|
caps: input.caps,
|
|
1432
|
-
frame: {
|
|
1492
|
+
frame: {
|
|
1493
|
+
frameNumber: input.frameNumber,
|
|
1494
|
+
...(input.frameSize === undefined ? {} : input.frameSize),
|
|
1495
|
+
},
|
|
1433
1496
|
generation: transaction.generation,
|
|
1434
1497
|
targets,
|
|
1435
1498
|
sceneData,
|
|
@@ -1455,21 +1518,43 @@ export function runRenderFeatureFrame(
|
|
|
1455
1518
|
host.setStatus(identity, 'failed', slot.latestError);
|
|
1456
1519
|
continue;
|
|
1457
1520
|
}
|
|
1521
|
+
const missing = missingCapability(feature, input.caps);
|
|
1522
|
+
if (missing !== undefined && hasActivePlan(frozen.value)) {
|
|
1523
|
+
const capabilityError = new RenderFeatureCapabilityMissingError(identity, order, missing);
|
|
1524
|
+
errors.push(capabilityError);
|
|
1525
|
+
transaction.abort();
|
|
1526
|
+
host.setStatus(identity, 'disabled', errorDescriptor(capabilityError));
|
|
1527
|
+
continue;
|
|
1528
|
+
}
|
|
1458
1529
|
const plannedFrame: RenderFeaturePlannedFrame = Object.freeze({
|
|
1459
1530
|
featureIdentity: identity,
|
|
1460
1531
|
generation: transaction.generation,
|
|
1461
1532
|
signature:
|
|
1462
1533
|
host.recordPlanSignature?.(identity, frozen.value) ??
|
|
1463
1534
|
renderFeaturePlanSignature(frozen.value),
|
|
1535
|
+
...(feature.placement === undefined ? {} : { placement: feature.placement }),
|
|
1464
1536
|
plan: frozen.value,
|
|
1465
1537
|
});
|
|
1466
1538
|
for (const resource of frozen.value.resources) {
|
|
1467
1539
|
if (resource.kind !== 'fullscreen-program') continue;
|
|
1468
|
-
|
|
1540
|
+
const entry = {
|
|
1469
1541
|
source: resource.source,
|
|
1542
|
+
...(resource.fragmentEntryPoint === undefined
|
|
1543
|
+
? {}
|
|
1544
|
+
: { fragmentEntryPoint: resource.fragmentEntryPoint }),
|
|
1470
1545
|
...(resource.reads === undefined ? {} : { reads: resource.reads }),
|
|
1546
|
+
...(resource.usesView === undefined ? {} : { usesView: resource.usesView }),
|
|
1547
|
+
...(resource.storageBindings === undefined
|
|
1548
|
+
? {}
|
|
1549
|
+
: { storageBindings: resource.storageBindings }),
|
|
1471
1550
|
...(resource.params === undefined ? {} : { params: resource.params }),
|
|
1472
|
-
}
|
|
1551
|
+
} satisfies PostProcessShaderEntry;
|
|
1552
|
+
// A feature may expose more than one graph-local fullscreen producer
|
|
1553
|
+
// (the cloud display composite and its shadow map). Keep each resource
|
|
1554
|
+
// addressable by its declared name and retain the feature identity alias
|
|
1555
|
+
// for the original public post-process route.
|
|
1556
|
+
fullscreenEffects.set(resource.name, entry);
|
|
1557
|
+
if (!fullscreenEffects.has(identity)) fullscreenEffects.set(identity, entry);
|
|
1473
1558
|
}
|
|
1474
1559
|
const prepared = preparePlanResources(slot, frozen.value, graphics, gpu, input.targets ?? []);
|
|
1475
1560
|
if (!prepared.ok) {
|
|
@@ -1499,8 +1584,34 @@ export function runRenderFeatureFrame(
|
|
|
1499
1584
|
resolver === undefined
|
|
1500
1585
|
? undefined
|
|
1501
1586
|
: (descriptor: import('./prepared-graphics').RenderFeatureGraphicsPassDescriptor) => {
|
|
1502
|
-
|
|
1503
|
-
|
|
1587
|
+
// A pending pass can be skipped while earlier passes remain usable.
|
|
1588
|
+
// Keep their shared resolver leases alive until submission retires them.
|
|
1589
|
+
const resolveGpuResource = (name: string) => {
|
|
1590
|
+
const owned = prepared.value.buffers.get(name);
|
|
1591
|
+
const borrowed = prepared.value.preparedGpuResources.get(name);
|
|
1592
|
+
const reference =
|
|
1593
|
+
owned ?? (borrowed?.kind === 'buffer' ? borrowed.reference : undefined);
|
|
1594
|
+
return reference === undefined ? undefined : gpu?.resolveBuffer(reference);
|
|
1595
|
+
};
|
|
1596
|
+
const resolved = resolveGraphicsSnapshot(
|
|
1597
|
+
resolver,
|
|
1598
|
+
descriptor,
|
|
1599
|
+
transaction.generation,
|
|
1600
|
+
resolveGpuResource,
|
|
1601
|
+
);
|
|
1602
|
+
// A pending pipeline is a retryable partial frame. The resolver
|
|
1603
|
+
// leases cover resources used by earlier ready passes and must
|
|
1604
|
+
// stay retained until the submitted batch retires; only terminal
|
|
1605
|
+
// resolution failures release them here.
|
|
1606
|
+
if (
|
|
1607
|
+
!resolved.ok &&
|
|
1608
|
+
!(
|
|
1609
|
+
resolved.error instanceof RenderFeaturePreparationFailedError &&
|
|
1610
|
+
resolved.error.detail.reason === 'pipeline-pending'
|
|
1611
|
+
)
|
|
1612
|
+
) {
|
|
1613
|
+
resolver.release();
|
|
1614
|
+
}
|
|
1504
1615
|
return resolved;
|
|
1505
1616
|
};
|
|
1506
1617
|
const releaseResolver = (): void => {
|
|
@@ -1529,9 +1640,11 @@ export function runRenderFeatureFrame(
|
|
|
1529
1640
|
host.setStatus(identity, 'failed', slot.latestError);
|
|
1530
1641
|
continue;
|
|
1531
1642
|
}
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1643
|
+
// Include partial allocations from skipped pending passes, even when no pass
|
|
1644
|
+
// completed. Fatal projection failures release the resolver above instead.
|
|
1645
|
+
const graphicsLeases =
|
|
1646
|
+
resolver?.leases ??
|
|
1647
|
+
projected.value.passes.flatMap((pass) => pass.resolvedGraphics?.leases ?? []);
|
|
1535
1648
|
if (graphicsLeases.length > 0) requiresPreparedResourceKey = true;
|
|
1536
1649
|
const leases = [...new Set(graphicsLeases), ...(gpu?.retireUntouched() ?? [])];
|
|
1537
1650
|
const retained = host.retainPreparedGraphics(identity, leases);
|
|
@@ -1564,6 +1677,7 @@ export function runRenderFeatureFrame(
|
|
|
1564
1677
|
errors,
|
|
1565
1678
|
plans,
|
|
1566
1679
|
fullscreenEffects,
|
|
1680
|
+
postProcessIdentities: Object.freeze([...postProcessIdentities]),
|
|
1567
1681
|
preparedResourceBatches,
|
|
1568
1682
|
requiresPreparedResourceKey,
|
|
1569
1683
|
hiddenEntityReports: mergeHiddenEntityReports(hiddenEntityReports),
|
|
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
|
|
|
2
2
|
import { SCENE_DATA_TEMPORAL_V1_SCHEMA } from '../../../temporal/scene-data';
|
|
3
3
|
import { createSceneDataCatalog } from '../../../temporal/scene-data-catalog';
|
|
4
4
|
import { freezeRenderFeaturePlan } from '../../plan';
|
|
5
|
-
import { planMotionBlur } from '../motion-blur-feature';
|
|
5
|
+
import { MOTION_BLUR_COMPUTE_WGSL, planMotionBlur } from '../motion-blur-feature';
|
|
6
6
|
import { DEFAULT_MOTION_BLUR_PARAMS } from '../motion-blur-params';
|
|
7
7
|
|
|
8
8
|
const caps = {
|
|
@@ -64,4 +64,114 @@ describe('Motion Blur feature plan', () => {
|
|
|
64
64
|
expect(pass.sampledTargets).not.toContain('motion-depth');
|
|
65
65
|
expect(catalog.schema).toBe(SCENE_DATA_TEMPORAL_V1_SCHEMA);
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
it('selects one tile summary and one fused reconstruction on compute-capable targets', () => {
|
|
69
|
+
const computeCaps = {
|
|
70
|
+
rgba16floatRenderable: true,
|
|
71
|
+
compute: true,
|
|
72
|
+
storageBuffer: true,
|
|
73
|
+
storageTexture: true,
|
|
74
|
+
} as never;
|
|
75
|
+
const catalog = createSceneDataCatalog({
|
|
76
|
+
featureIdentity: 'forgeax.motion-blur',
|
|
77
|
+
generation: 4,
|
|
78
|
+
planIdentity: 'forgeax.motion-blur:4',
|
|
79
|
+
rgba16floatRenderable: true,
|
|
80
|
+
});
|
|
81
|
+
const targets = [
|
|
82
|
+
{
|
|
83
|
+
name: 'motion-input',
|
|
84
|
+
kind: 'color' as const,
|
|
85
|
+
format: 'rgba16float' as const,
|
|
86
|
+
sampleCount: 1 as const,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'motion-output',
|
|
90
|
+
kind: 'color' as const,
|
|
91
|
+
format: 'rgba16float' as const,
|
|
92
|
+
sampleCount: 1 as const,
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
const planned = planMotionBlur(
|
|
96
|
+
DEFAULT_MOTION_BLUR_PARAMS,
|
|
97
|
+
{
|
|
98
|
+
caps: computeCaps,
|
|
99
|
+
frame: { frameNumber: 7, width: 1920, height: 1080 },
|
|
100
|
+
generation: 4,
|
|
101
|
+
targets,
|
|
102
|
+
sceneData: catalog,
|
|
103
|
+
},
|
|
104
|
+
{ frameDeltaSeconds: 1 / 60, reset: false },
|
|
105
|
+
);
|
|
106
|
+
expect(planned.ok).toBe(true);
|
|
107
|
+
if (!planned.ok) return;
|
|
108
|
+
const frozen = freezeRenderFeaturePlan('forgeax.motion-blur', planned.value, targets);
|
|
109
|
+
expect(frozen.ok).toBe(true);
|
|
110
|
+
if (!frozen.ok) return;
|
|
111
|
+
|
|
112
|
+
const computeProgram = frozen.value.resources.find(
|
|
113
|
+
(resource) => resource.kind === 'compute-program',
|
|
114
|
+
);
|
|
115
|
+
const tileSummary = frozen.value.resources.find(
|
|
116
|
+
(resource) => resource.kind === 'buffer' && resource.name === 'motion-blur-tile-summary',
|
|
117
|
+
);
|
|
118
|
+
expect(computeProgram?.kind).toBe('compute-program');
|
|
119
|
+
expect(tileSummary).toMatchObject({
|
|
120
|
+
kind: 'buffer',
|
|
121
|
+
size: Math.ceil(1920 / 16) * Math.ceil(1080 / 16) * 32,
|
|
122
|
+
usage: ['storage'],
|
|
123
|
+
});
|
|
124
|
+
expect(frozen.value.passes.map((pass) => pass.name)).toEqual([
|
|
125
|
+
'motion-blur-tile-summary',
|
|
126
|
+
'motion-blur',
|
|
127
|
+
]);
|
|
128
|
+
expect(frozen.value.passes).toHaveLength(2);
|
|
129
|
+
expect(frozen.value.passes[0]).toMatchObject({
|
|
130
|
+
kind: 'compute',
|
|
131
|
+
dispatches: [{ entryPoint: 'tile_summary', workgroups: [120, 68, 1] }],
|
|
132
|
+
});
|
|
133
|
+
expect(frozen.value.passes[1]).toMatchObject({
|
|
134
|
+
kind: 'compute',
|
|
135
|
+
dispatches: [{ entryPoint: 'reconstruct', workgroups: [240, 135, 1] }],
|
|
136
|
+
});
|
|
137
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('2.0 * (f32(index) + 0.5) / denominator - 1.0');
|
|
138
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('let sourcePixel = workgroupBase');
|
|
139
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('halfFilteredColor');
|
|
140
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('workgroupBarrier()');
|
|
141
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('if (!inBounds) {');
|
|
142
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('depthReject');
|
|
143
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('sourceVelocitySegmentCovers');
|
|
144
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('TILE_NEIGHBORHOOD_COUNT');
|
|
145
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('tileIntersectsWorkgroupSupport');
|
|
146
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('tileNeighborhoodOffset');
|
|
147
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('const EDGE_FILL_FACTOR : f32 = 0.99;');
|
|
148
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('let acceptedColor');
|
|
149
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('let acceptedAlpha');
|
|
150
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('let emptyReceiver');
|
|
151
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('let sourceScale');
|
|
152
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('let sourceContribution');
|
|
153
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('let trailScale');
|
|
154
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).toContain('let outputAlpha');
|
|
155
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).not.toContain('TILE_CANDIDATE_OFFSETS');
|
|
156
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).not.toContain('atomic');
|
|
157
|
+
expect(MOTION_BLUR_COMPUTE_WGSL).not.toContain('textureSampleLevel');
|
|
158
|
+
if (computeProgram?.kind === 'compute-program') {
|
|
159
|
+
const entries = computeProgram.program.bindings?.[0]?.entries ?? [];
|
|
160
|
+
expect(entries.find((entry) => entry.binding === 2)?.buffer?.type).toBe('storage');
|
|
161
|
+
expect(entries.find((entry) => entry.binding === 3)?.storageTexture?.access).toBe(
|
|
162
|
+
'write-only',
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('compiles the compute lane WGSL before it reaches a backend', async () => {
|
|
168
|
+
const { compileShader } = await import(
|
|
169
|
+
/* @vite-ignore */
|
|
170
|
+
new URL('../../../../../shader-compiler/dist/index.mjs', import.meta.url).href
|
|
171
|
+
);
|
|
172
|
+
const compiled = await compileShader(MOTION_BLUR_COMPUTE_WGSL, {
|
|
173
|
+
id: 'forgeax::motion-blur-compute',
|
|
174
|
+
});
|
|
175
|
+
expect(compiled.ok, compiled.ok ? undefined : String(compiled.error)).toBe(true);
|
|
176
|
+
});
|
|
67
177
|
});
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import {
|
|
3
3
|
DEFAULT_MOTION_BLUR_PARAMS,
|
|
4
|
+
effectiveMotionBlurSampleCount,
|
|
5
|
+
isMotionBlurIntervalValid,
|
|
6
|
+
motionBlurExposureScale,
|
|
7
|
+
motionBlurSampleDelta,
|
|
4
8
|
motionBlurTemporalDemand,
|
|
5
9
|
validateMotionBlurParams,
|
|
6
10
|
} from '../motion-blur-params';
|
|
@@ -12,6 +16,7 @@ describe('Motion Blur parameter validation', () => {
|
|
|
12
16
|
shutterAngle: 180,
|
|
13
17
|
maxRadiusPixels: 32,
|
|
14
18
|
sampleCount: 8,
|
|
19
|
+
targetFps: 60,
|
|
15
20
|
});
|
|
16
21
|
});
|
|
17
22
|
|
|
@@ -32,6 +37,9 @@ describe('Motion Blur parameter validation', () => {
|
|
|
32
37
|
['sampleCount', 3],
|
|
33
38
|
['sampleCount', 17],
|
|
34
39
|
['sampleCount', 8.5],
|
|
40
|
+
['targetFps', -1],
|
|
41
|
+
['targetFps', 240.5],
|
|
42
|
+
['targetFps', 59.5],
|
|
35
43
|
] as const)('returns structured failure for %s=%s', (field, value) => {
|
|
36
44
|
const result = validateMotionBlurParams({ [field]: value });
|
|
37
45
|
expect(result.ok).toBe(false);
|
|
@@ -45,9 +53,56 @@ describe('Motion Blur parameter validation', () => {
|
|
|
45
53
|
|
|
46
54
|
it('does no temporal work when omitted or shutter is zero', () => {
|
|
47
55
|
expect(motionBlurTemporalDemand(undefined)).toBe(false);
|
|
48
|
-
expect(
|
|
49
|
-
|
|
50
|
-
|
|
56
|
+
expect(
|
|
57
|
+
motionBlurTemporalDemand({
|
|
58
|
+
shutterAngle: 0,
|
|
59
|
+
maxRadiusPixels: 32,
|
|
60
|
+
sampleCount: 8,
|
|
61
|
+
targetFps: 60,
|
|
62
|
+
}),
|
|
63
|
+
).toBe(false);
|
|
64
|
+
expect(
|
|
65
|
+
motionBlurTemporalDemand({
|
|
66
|
+
shutterAngle: 180,
|
|
67
|
+
maxRadiusPixels: 0,
|
|
68
|
+
sampleCount: 8,
|
|
69
|
+
targetFps: 60,
|
|
70
|
+
}),
|
|
71
|
+
).toBe(false);
|
|
51
72
|
expect(motionBlurTemporalDemand(DEFAULT_MOTION_BLUR_PARAMS)).toBe(true);
|
|
52
73
|
});
|
|
74
|
+
|
|
75
|
+
it('rounds authored sample budgets down to the fixed shader tiers', () => {
|
|
76
|
+
expect(effectiveMotionBlurSampleCount(3)).toBe(0);
|
|
77
|
+
expect(effectiveMotionBlurSampleCount(4)).toBe(4);
|
|
78
|
+
expect(effectiveMotionBlurSampleCount(7)).toBe(4);
|
|
79
|
+
expect(effectiveMotionBlurSampleCount(8)).toBe(8);
|
|
80
|
+
expect(effectiveMotionBlurSampleCount(15)).toBe(8);
|
|
81
|
+
expect(effectiveMotionBlurSampleCount(16)).toBe(16);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('rejects unstable intervals and scales displacement to the target rate', () => {
|
|
85
|
+
expect(isMotionBlurIntervalValid(1 / 60)).toBe(true);
|
|
86
|
+
expect(isMotionBlurIntervalValid(0)).toBe(false);
|
|
87
|
+
expect(isMotionBlurIntervalValid(0.101)).toBe(false);
|
|
88
|
+
expect(motionBlurExposureScale(1 / 60, 60)).toBeCloseTo(1);
|
|
89
|
+
expect(motionBlurExposureScale(1 / 120, 60)).toBeCloseTo(2);
|
|
90
|
+
expect(motionBlurExposureScale(1 / 60, 0)).toBe(1);
|
|
91
|
+
expect(motionBlurExposureScale(0, 60)).toBe(0);
|
|
92
|
+
expect(motionBlurExposureScale(1 / 60, 60.5)).toBe(0);
|
|
93
|
+
expect(motionBlurExposureScale(1 / 60, 241)).toBe(0);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('keeps raw render hitches visible before ECS clamp policy', () => {
|
|
97
|
+
expect(motionBlurSampleDelta(1.2, 1, 0.1)).toBeCloseTo(0.2);
|
|
98
|
+
expect(motionBlurSampleDelta(1 / 30, 0, 0.1)).toBeCloseTo(1 / 30);
|
|
99
|
+
expect(isMotionBlurIntervalValid(motionBlurSampleDelta(1.2, 1, 0.1))).toBe(false);
|
|
100
|
+
expect(isMotionBlurIntervalValid(motionBlurSampleDelta(1 / 30, 0, 0.1))).toBe(true);
|
|
101
|
+
expect(motionBlurSampleDelta(undefined, undefined, 0.1)).toBe(0.1);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('fails closed for an explicitly invalid host/replay sample', () => {
|
|
105
|
+
expect(Number.isNaN(motionBlurSampleDelta(Number.NaN, 1, 1 / 60))).toBe(true);
|
|
106
|
+
expect(Number.isNaN(motionBlurSampleDelta(1, Number.POSITIVE_INFINITY, 1 / 60))).toBe(true);
|
|
107
|
+
});
|
|
53
108
|
});
|