@forgeax/engine-render 0.1.20 → 0.1.23
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 +365 -29
- package/dist/assembly/backend-contract.d.ts +13 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/device-feature-admission.d.ts +18 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -0
- package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
- package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +30 -19
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +19 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/render-target-host.d.ts +46 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -0
- package/dist/assets/render-asset-port.d.ts.map +1 -1
- package/dist/authoring.mjs +4 -1
- package/dist/authoring.mjs.map +1 -1
- package/dist/capture/cube-views.d.ts +21 -0
- package/dist/capture/cube-views.d.ts.map +1 -0
- package/dist/capture/scheduler.d.ts +54 -0
- package/dist/capture/scheduler.d.ts.map +1 -0
- package/dist/{chunk-PCHBPYML.mjs → chunk-4L3P6DT5.mjs} +2 -2
- package/dist/chunk-4L3P6DT5.mjs.map +1 -0
- package/dist/{chunk-VFPLTKCU.mjs → chunk-4NPUASZR.mjs} +15 -4
- package/dist/chunk-4NPUASZR.mjs.map +1 -0
- package/dist/chunk-DIYW3M5D.mjs +5085 -0
- package/dist/chunk-DIYW3M5D.mjs.map +1 -0
- package/dist/chunk-FBC4R44J.mjs +1003 -0
- package/dist/chunk-FBC4R44J.mjs.map +1 -0
- package/dist/{chunk-CDTWTHZR.mjs → chunk-FF7K3FSO.mjs} +474 -168
- package/dist/chunk-FF7K3FSO.mjs.map +1 -0
- package/dist/chunk-HZUPSYW7.mjs +1104 -0
- package/dist/chunk-HZUPSYW7.mjs.map +1 -0
- package/dist/{chunk-TBQJOK2L.mjs → chunk-QODA5UKU.mjs} +321 -269
- package/dist/chunk-QODA5UKU.mjs.map +1 -0
- package/dist/chunk-YALPS44A.mjs +296 -0
- package/dist/chunk-YALPS44A.mjs.map +1 -0
- package/dist/{chunk-4XINDLAY.mjs → chunk-ZUWKAZ2I.mjs} +1963 -2178
- package/dist/chunk-ZUWKAZ2I.mjs.map +1 -0
- package/dist/cluster-binner.d.ts +5 -0
- package/dist/cluster-binner.d.ts.map +1 -1
- package/dist/components/camera.d.ts +1 -0
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/cube-camera.d.ts +20 -0
- package/dist/components/cube-camera.d.ts.map +1 -0
- package/dist/components/directional-light.d.ts +11 -2
- package/dist/components/directional-light.d.ts.map +1 -1
- package/dist/components/directional-shadow-filter.d.ts +25 -0
- package/dist/components/directional-shadow-filter.d.ts.map +1 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts +4 -0
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/light-probe.d.ts +9 -0
- package/dist/components/light-probe.d.ts.map +1 -0
- package/dist/components/rect-area-light.d.ts +12 -0
- package/dist/components/rect-area-light.d.ts.map +1 -0
- package/dist/components/reflection-probe.d.ts +17 -0
- package/dist/components/reflection-probe.d.ts.map +1 -0
- package/dist/components/scene-instance.d.ts +4 -0
- package/dist/components/scene-instance.d.ts.map +1 -1
- package/dist/components/spot-light.d.ts +3 -0
- package/dist/components/spot-light.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +14836 -9620
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +8 -1
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/device/lifecycle-transaction.d.ts +2 -0
- package/dist/device/lifecycle-transaction.d.ts.map +1 -0
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +5 -0
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/gpu-driven.d.ts +26 -0
- package/dist/errors/gpu-driven.d.ts.map +1 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +9 -1
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +166 -93
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/directional-shadow-projection.d.ts +23 -0
- package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
- package/dist/extract/environment.d.ts +14 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +50 -0
- package/dist/extract/gpu-driven.d.ts.map +1 -0
- package/dist/extract/visibility.d.ts.map +1 -1
- package/dist/features/fullscreen.d.ts.map +1 -1
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +10 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +13 -2
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +34 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts +63 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +97 -2
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/view-gpu.d.ts +64 -1
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts +14 -0
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +8 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-usage.d.ts +0 -1
- package/dist/gpu-usage.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +21 -19
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +4 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/kernel-cache.d.ts +36 -0
- package/dist/ibl/kernel-cache.d.ts.map +1 -0
- package/dist/index.d.ts +39 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +91 -6
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +214 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances-derived-bounds.d.ts +50 -0
- package/dist/instances-derived-bounds.d.ts.map +1 -0
- package/dist/internal.d.ts +9 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +23 -2
- package/dist/internal.mjs.map +1 -1
- package/dist/light-buffer-layout.d.ts +58 -140
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +54 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +38 -14
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts +2 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
- package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
- package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
- package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
- package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
- package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
- package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts +4 -13
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline/standard-profile.d.ts +5 -26
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +2 -0
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +40 -7
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/point-shadow-inspection.d.ts +21 -0
- package/dist/point-shadow-inspection.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
- package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/resources.d.ts +72 -0
- package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/state.d.ts +24 -0
- package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +33 -36
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +78 -24
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts +5 -0
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +16 -6
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
- package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
- package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/index.d.ts +8 -0
- package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
- package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/session.d.ts +43 -0
- package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +20 -3
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +0 -20
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +6 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +25 -2
- 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 +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +98 -6
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +119 -4
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +7 -5
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/reflection/filter.d.ts +22 -0
- package/dist/reflection/filter.d.ts.map +1 -0
- package/dist/reflection/gpu-table.d.ts +25 -0
- package/dist/reflection/gpu-table.d.ts.map +1 -0
- package/dist/reflection/inspection.d.ts +10 -0
- package/dist/reflection/inspection.d.ts.map +1 -0
- package/dist/reflection/projection.d.ts +140 -0
- package/dist/reflection/projection.d.ts.map +1 -0
- package/dist/reflection/record-owner.d.ts +60 -0
- package/dist/reflection/record-owner.d.ts.map +1 -0
- package/dist/render-contract.d.ts +62 -14
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +1 -0
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +49 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +160 -31
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +28 -2
- package/dist/render-system.d.ts.map +1 -1
- package/dist/renderer.d.ts +43 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/scene/probe-blend-record.d.ts +22 -0
- package/dist/scene/probe-blend-record.d.ts.map +1 -0
- package/dist/scene/probe-blend.d.ts +142 -0
- package/dist/scene/probe-blend.d.ts.map +1 -0
- package/dist/scene/render-scene-types.d.ts +0 -6
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +117 -9
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/visibility/bounds.d.ts +20 -0
- package/dist/scene/visibility/bounds.d.ts.map +1 -0
- package/dist/scene/visibility/budget.d.ts +16 -0
- package/dist/scene/visibility/budget.d.ts.map +1 -0
- package/dist/scene/visibility/facet.d.ts +73 -0
- package/dist/scene/visibility/facet.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-lod.d.ts +46 -0
- package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
- package/dist/scene/visibility/inspection.d.ts +132 -0
- package/dist/scene/visibility/inspection.d.ts.map +1 -0
- package/dist/scene/visibility/lod-selector.d.ts +25 -0
- package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
- package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
- package/dist/scene/visibility/types.d.ts +34 -0
- package/dist/scene/visibility/types.d.ts.map +1 -0
- package/dist/shadow-atlas.d.ts +3 -3
- package/dist/shadow-atlas.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +3 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/ssr/admission.d.ts +122 -0
- package/dist/ssr/admission.d.ts.map +1 -0
- package/dist/ssr/composition.d.ts +32 -0
- package/dist/ssr/composition.d.ts.map +1 -0
- package/dist/ssr/errors.d.ts +39 -0
- package/dist/ssr/errors.d.ts.map +1 -0
- package/dist/ssr/identity.d.ts +13 -0
- package/dist/ssr/identity.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +1 -1
- package/dist/targets/contracts.d.ts +66 -0
- package/dist/targets/contracts.d.ts.map +1 -0
- package/dist/targets/graph-projection.d.ts +29 -0
- package/dist/targets/graph-projection.d.ts.map +1 -0
- package/dist/targets/material-source.d.ts +34 -0
- package/dist/targets/material-source.d.ts.map +1 -0
- package/dist/targets/owner.d.ts +32 -0
- package/dist/targets/owner.d.ts.map +1 -0
- package/dist/targets/physical.d.ts +18 -0
- package/dist/targets/physical.d.ts.map +1 -0
- package/dist/targets/readback.d.ts +39 -0
- package/dist/targets/readback.d.ts.map +1 -0
- package/dist/temporal/frame-coordinator.d.ts +13 -0
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +2 -0
- package/dist/temporal/frame.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -5
- package/dist/temporal/view.d.ts +7 -0
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/tilemap-chunk-extract-system.d.ts +1 -1
- package/dist/typed-render-graph-primitives.d.ts +5 -1
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +1 -1
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +9 -5
- package/dist/volume/passes.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
- package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
- package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
- package/src/__tests__/cluster-binner.unit.test.ts +35 -0
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +12 -2
- package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
- package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
- package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
- package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
- package/src/__tests__/cube-camera.integration.test.ts +42 -0
- package/src/__tests__/detached-inspection.integration.test.ts +6 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +85 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +62 -6
- package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
- package/src/__tests__/environment-generation.integration.test.ts +16 -0
- package/src/__tests__/evidence-identity.ts +13 -0
- package/src/__tests__/evidence-identity.unit.test.ts +24 -0
- package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
- package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
- package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
- package/src/__tests__/factory-contract.integration.test.ts +288 -29
- package/src/__tests__/fog-component.unit.test.ts +67 -0
- package/src/__tests__/fog.integration.test.ts +86 -0
- package/src/__tests__/frame-observation.contract.test.ts +15 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -8
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +18 -1
- package/src/__tests__/gpu-driven-production.integration.test.ts +579 -17
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +101 -6
- package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
- package/src/__tests__/gpu-lod-evidence.ts +188 -0
- package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
- package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
- package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
- package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
- package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
- package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
- package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
- package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
- package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
- package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
- package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
- package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
- package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
- package/src/__tests__/gpu-scene.unit.test.ts +49 -3
- package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
- package/src/__tests__/instances-culling.integration.test.ts +94 -0
- package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
- package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
- package/src/__tests__/light-inspection.unit.test.ts +55 -0
- package/src/__tests__/light-resource-error.unit.test.ts +43 -0
- package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
- package/src/__tests__/lod-bounds.unit.test.ts +42 -0
- package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
- package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
- package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
- package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
- package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
- package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
- package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
- package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
- package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
- package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
- package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
- package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
- package/src/__tests__/lod-selector.profile.test.ts +35 -0
- package/src/__tests__/lod-selector.unit.test.ts +68 -0
- package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
- package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
- package/src/__tests__/ltc-resources.unit.test.ts +32 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +17 -0
- package/src/__tests__/material-observation.integration.test.ts +101 -0
- package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
- package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
- package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
- package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
- package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
- package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
- package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
- package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
- package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
- package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
- package/src/__tests__/occlusion-query.evidence.ts +178 -0
- package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
- package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
- package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
- package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
- package/src/__tests__/probe-bindings.unit.test.ts +200 -0
- package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
- package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
- package/src/__tests__/probe-capacity.integration.test.ts +97 -0
- package/src/__tests__/probe-recovery.integration.test.ts +104 -0
- package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
- package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
- package/src/__tests__/profiler-phase-token.test.ts +1 -0
- package/src/__tests__/public-surface.test-d.ts +10 -0
- package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
- package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
- package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
- package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
- package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
- package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
- package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
- package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
- package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
- package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
- package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
- package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +19 -3
- package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
- package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
- package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
- package/src/__tests__/render-target-admission.unit.test.ts +80 -0
- package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
- package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
- package/src/__tests__/render-target-material-source.test-d.ts +30 -0
- package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
- package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
- package/src/__tests__/render-target-owner.unit.test.ts +122 -0
- package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
- package/src/__tests__/render-target-public-schema.json +107 -0
- package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
- package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
- package/src/__tests__/render-target-readback.integration.test.ts +90 -0
- package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +124 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
- package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
- package/src/__tests__/skin-motion-regression.unit.test.ts +154 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +13 -4
- package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
- package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
- package/src/__tests__/ssr-composition.unit.test.ts +46 -0
- package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
- package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
- package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
- package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +299 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +15 -5
- package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
- package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
- package/src/__tests__/standard-lighting-write.unit.test.ts +441 -0
- package/src/__tests__/standard-lighting.integration.test.ts +67 -0
- package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
- package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
- package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
- package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -38
- package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
- package/src/__tests__/temporal-view.unit.test.ts +3 -3
- package/src/__tests__/transmission-prewarm.unit.test.ts +69 -0
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
- package/src/__tests__/visibility-budget.integration.test.ts +140 -0
- package/src/__tests__/visibility-budget.unit.test.ts +70 -0
- package/src/__tests__/visibility-extract.integration.test.ts +11 -6
- package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
- package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
- package/src/assembly/backend-contract.ts +13 -0
- package/src/assembly/device-feature-admission.ts +80 -0
- package/src/assembly/directional-shadow-inspection.ts +122 -0
- package/src/assembly/factory.ts +1411 -366
- package/src/assembly/host-contract.ts +35 -0
- package/src/assembly/render-target-host.ts +847 -0
- package/src/assets/asset-decoders.ts +1 -1
- package/src/assets/render-asset-port.ts +7 -1
- package/src/capture/cube-views.ts +69 -0
- package/src/capture/scheduler.ts +265 -0
- package/src/cluster-binner.ts +31 -0
- package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
- package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
- package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
- package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
- package/src/components/camera.ts +4 -0
- package/src/components/cube-camera.ts +52 -0
- package/src/components/directional-light.ts +22 -2
- package/src/components/directional-shadow-filter.ts +57 -0
- package/src/components/index.ts +5 -0
- package/src/components/light-helpers.ts +133 -8
- package/src/components/light-probe.ts +13 -0
- package/src/components/rect-area-light.ts +15 -0
- package/src/components/reflection-probe.ts +49 -0
- package/src/components/scene-instance.ts +6 -0
- package/src/components/spot-light.ts +3 -0
- package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
- package/src/device/gpu-residency.ts +140 -9
- package/src/device/lifecycle-transaction.ts +12 -0
- package/src/environment/frame.ts +6 -24
- package/src/environment/lifecycle.ts +20 -1
- package/src/errors/gpu-driven.ts +92 -0
- package/src/errors/index.ts +1 -0
- package/src/errors/recover.ts +32 -0
- package/src/errors/render.ts +341 -143
- package/src/extract/camera.ts +3 -3
- package/src/extract/directional-shadow-projection.ts +61 -0
- package/src/extract/environment.ts +57 -0
- package/src/extract/gpu-driven.ts +108 -0
- package/src/extract/visibility.ts +2 -1
- package/src/features/fullscreen.ts +3 -0
- package/src/features/targets.ts +4 -1
- package/src/features/types.ts +10 -0
- package/src/fullscreen-post-process-pass.ts +43 -2
- package/src/gpu-driven/batch-topology.ts +207 -28
- package/src/gpu-driven/prepared-draw.ts +208 -0
- package/src/gpu-driven/production-raster.ts +953 -43
- package/src/gpu-driven/view-gpu.ts +411 -29
- package/src/gpu-scene-schema.ts +13 -0
- package/src/gpu-scene.ts +140 -64
- package/src/gpu-usage.ts +0 -1
- package/src/hdrp-buffers.ts +169 -63
- package/src/ibl/IblPipelineCache.ts +11 -0
- package/src/ibl/kernel-cache.ts +88 -0
- package/src/index.ts +222 -0
- package/src/inspection-types.ts +276 -1
- package/src/instances-derived-bounds.ts +171 -0
- package/src/internal.ts +38 -0
- package/src/light-buffer-layout.ts +155 -310
- package/src/materials.ts +16 -2
- package/src/mesh-material-bindings.ts +132 -0
- package/src/pbr-pipeline.ts +255 -60
- package/src/pipeline/standard-forward-lane.ts +93 -16
- package/src/pipeline/standard-lighting/errors.ts +6 -0
- package/src/pipeline/standard-lighting/graph.ts +158 -0
- package/src/pipeline/standard-lighting/inspection.ts +88 -0
- package/src/pipeline/standard-lighting/layout.ts +31 -0
- package/src/pipeline/standard-lighting/light-frame.ts +35 -0
- package/src/pipeline/standard-lighting/membership.ts +43 -0
- package/src/pipeline/standard-lighting/prepare.ts +37 -0
- package/src/pipeline/standard-lighting/topology.ts +120 -0
- package/src/pipeline/standard-lighting/transport.ts +78 -0
- package/src/pipeline/standard-pipeline.ts +124 -193
- package/src/pipeline/standard-post.ts +26 -7
- package/src/pipeline/standard-profile.ts +17 -47
- package/src/pipeline-builder.ts +5 -2
- package/src/pipeline-spec.ts +95 -21
- package/src/plugin.ts +4 -0
- package/src/point-shadow-inspection.ts +55 -0
- package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
- package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
- package/src/prepare/extended-lighting/resources.ts +389 -0
- package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
- package/src/prepare/extended-lighting/state.ts +92 -0
- package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
- package/src/record/__tests__/temporal-payload.unit.test.ts +64 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
- package/src/record/frame-lighting.ts +591 -452
- package/src/record/frame-snapshot.ts +92 -39
- package/src/record/frame-targets.ts +17 -0
- package/src/record/frame.ts +662 -158
- package/src/record/gpu-pass-timing/contract.ts +180 -0
- package/src/record/gpu-pass-timing/errors.ts +34 -0
- package/src/record/gpu-pass-timing/index.ts +37 -0
- package/src/record/gpu-pass-timing/parser.ts +97 -0
- package/src/record/gpu-pass-timing/session.ts +938 -0
- package/src/record/gpu-timing.ts +112 -39
- package/src/record/helpers.ts +0 -58
- package/src/record/main-pass-geometry.ts +324 -119
- package/src/record/main-pass-material.ts +103 -10
- package/src/record/main-pass-sprite-draws.ts +99 -103
- package/src/record/main-pass.ts +71 -15
- package/src/record/mesh-ssbo.ts +47 -36
- package/src/record/render-context.ts +136 -3
- package/src/record/shadow-pass.ts +83 -68
- package/src/record/skybox-post-pass.ts +20 -4
- package/src/record/typed-frame-graph.ts +1034 -43
- package/src/record/view-ubo.ts +72 -47
- package/src/reflection/filter.ts +81 -0
- package/src/reflection/gpu-table.ts +44 -0
- package/src/reflection/inspection.ts +67 -0
- package/src/reflection/projection.ts +476 -0
- package/src/reflection/record-owner.ts +1283 -0
- package/src/render-contract.ts +93 -10
- package/src/render-graph-primitives.ts +9 -4
- package/src/render-pipeline.ts +122 -2
- package/src/render-system-extract.ts +1041 -225
- package/src/render-system.ts +1310 -85
- package/src/renderer.ts +222 -0
- package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
- package/src/scene/probe-blend-record.ts +54 -0
- package/src/scene/probe-blend.ts +813 -0
- package/src/scene/render-scene-types.ts +0 -7
- package/src/scene/render-scene.ts +942 -171
- package/src/scene/visibility/bounds.ts +57 -0
- package/src/scene/visibility/budget.ts +40 -0
- package/src/scene/visibility/facet.ts +400 -0
- package/src/scene/visibility/gpu-frame-timing.ts +101 -0
- package/src/scene/visibility/gpu-lod.ts +119 -0
- package/src/scene/visibility/inspection.ts +313 -0
- package/src/scene/visibility/lod-selector.ts +84 -0
- package/src/scene/visibility/occlusion-confidence.ts +478 -0
- package/src/scene/visibility/occlusion-pass.ts +165 -0
- package/src/scene/visibility/occlusion-query-pool.ts +178 -0
- package/src/scene/visibility/occlusion-runtime.ts +672 -0
- package/src/scene/visibility/types.ts +50 -0
- package/src/shadow-atlas.ts +5 -5
- package/src/ssao-buffers.ts +9 -2
- package/src/ssr/admission.ts +451 -0
- package/src/ssr/composition.ts +73 -0
- package/src/ssr/errors.ts +76 -0
- package/src/ssr/identity.ts +12 -0
- package/src/systems/skin-palette-allocator.ts +1 -1
- package/src/targets/contracts.ts +182 -0
- package/src/targets/graph-projection.ts +169 -0
- package/src/targets/material-source.ts +143 -0
- package/src/targets/owner.ts +214 -0
- package/src/targets/physical.ts +18 -0
- package/src/targets/readback.ts +153 -0
- package/src/temporal/frame-coordinator.ts +26 -0
- package/src/temporal/frame.ts +14 -1
- package/src/temporal/view.ts +11 -0
- package/src/tilemap-chunk-extract-system.ts +4 -4
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
- package/src/typed-render-graph-primitives.ts +53 -3
- package/src/typed-shadow-passes.ts +46 -40
- package/src/volume/passes.ts +61 -58
- package/dist/.tsbuildinfo +0 -1
- package/dist/chunk-4XINDLAY.mjs.map +0 -1
- package/dist/chunk-CDTWTHZR.mjs.map +0 -1
- package/dist/chunk-M2MP4ZOU.mjs +0 -73
- package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
- package/dist/chunk-PCHBPYML.mjs.map +0 -1
- package/dist/chunk-TBQJOK2L.mjs.map +0 -1
- package/dist/chunk-VFPLTKCU.mjs.map +0 -1
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
2
|
+
import type { PreparedStandardLighting } from './prepare';
|
|
3
|
+
import type { StandardClusterTransport } from './transport';
|
|
4
|
+
|
|
5
|
+
/** A prepared frame with no local lights on a non-storage backend. */
|
|
6
|
+
export interface StandardNoLocalTopologyInput {
|
|
7
|
+
readonly kind: 'no-local-lights';
|
|
8
|
+
readonly prepared: PreparedStandardLighting;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** A prepared frame whose Standard surface uses one proven Cluster transport. */
|
|
12
|
+
export interface StandardClusteredTopologyInput {
|
|
13
|
+
readonly kind: 'clustered';
|
|
14
|
+
readonly prepared: PreparedStandardLighting;
|
|
15
|
+
readonly transport: StandardClusterTransport;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The only lighting value accepted by a Standard topology adapter. It is a
|
|
20
|
+
* projection of one prepared frame, not a second light/config/capability
|
|
21
|
+
* input. Both Forward and Deferred keep the same object identity for a frame.
|
|
22
|
+
*/
|
|
23
|
+
export type StandardTopologyInput = StandardNoLocalTopologyInput | StandardClusteredTopologyInput;
|
|
24
|
+
|
|
25
|
+
export type StandardTopologyInputValue = StandardTopologyInput;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Stable identity for the graph-facing Standard lighting declaration.
|
|
29
|
+
*
|
|
30
|
+
* The prepared light payload itself is frame-local and must never be retained
|
|
31
|
+
* by a compiled graph. These are the only facts that affect the Cluster graph
|
|
32
|
+
* shape and persistent buffer contract, so the record owner can reject an old
|
|
33
|
+
* graph before uploading a payload derived from a different declaration.
|
|
34
|
+
*/
|
|
35
|
+
export function standardLightingTopologySignature(
|
|
36
|
+
input: StandardTopologyInputValue | undefined,
|
|
37
|
+
): string {
|
|
38
|
+
if (input === undefined) return 'missing';
|
|
39
|
+
if (input.kind === 'no-local-lights') return 'no-local-lights';
|
|
40
|
+
return JSON.stringify({
|
|
41
|
+
kind: input.kind,
|
|
42
|
+
transport: input.transport.kind,
|
|
43
|
+
producer: input.transport.producer,
|
|
44
|
+
grid: input.prepared.layout.grid,
|
|
45
|
+
clusterGridU32Length: input.prepared.layout.clusterGridU32Length,
|
|
46
|
+
lightIndexListCapacity: input.prepared.layout.lightIndexListCapacity,
|
|
47
|
+
lightDataSlotCount: input.prepared.layout.lightDataSlotCount,
|
|
48
|
+
lightBoundsInt32Length: input.prepared.layout.lightBoundsInt32Length,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface StandardTopologyInputError {
|
|
53
|
+
readonly code: 'topology-input-invalid';
|
|
54
|
+
readonly expected: 'prepared Standard lighting topology input';
|
|
55
|
+
readonly hint: 'derive topology from prepared Standard lighting';
|
|
56
|
+
readonly detail: {
|
|
57
|
+
readonly field: 'kind' | 'prepared' | 'transport' | 'lights' | 'capabilities';
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function invalid(
|
|
62
|
+
field: StandardTopologyInputError['detail']['field'],
|
|
63
|
+
): Result<never, StandardTopologyInputError> {
|
|
64
|
+
return err({
|
|
65
|
+
code: 'topology-input-invalid',
|
|
66
|
+
expected: 'prepared Standard lighting topology input',
|
|
67
|
+
hint: 'derive topology from prepared Standard lighting',
|
|
68
|
+
detail: { field },
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Validate that transport and prepared membership are the same derivation.
|
|
74
|
+
* The identity checks make it impossible for an adapter to silently combine
|
|
75
|
+
* one path's layout/counts with another path's prepared light corpus.
|
|
76
|
+
*/
|
|
77
|
+
export function deriveStandardTopologyInput(
|
|
78
|
+
input: StandardTopologyInput,
|
|
79
|
+
): Result<StandardTopologyInputValue, StandardTopologyInputError> {
|
|
80
|
+
const candidate = input as StandardTopologyInput & {
|
|
81
|
+
readonly kind?: unknown;
|
|
82
|
+
readonly lights?: unknown;
|
|
83
|
+
readonly capabilities?: unknown;
|
|
84
|
+
readonly transport?: unknown;
|
|
85
|
+
};
|
|
86
|
+
if ('lights' in candidate) return invalid('lights');
|
|
87
|
+
if ('capabilities' in candidate) return invalid('capabilities');
|
|
88
|
+
if (input === null || typeof input !== 'object') return invalid('kind');
|
|
89
|
+
if (input.prepared === null || typeof input.prepared !== 'object') {
|
|
90
|
+
return invalid('prepared');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const prepared = input.prepared;
|
|
94
|
+
if (input.kind === 'no-local-lights') {
|
|
95
|
+
if (prepared.local.length !== 0 || 'transport' in candidate) return invalid('transport');
|
|
96
|
+
return ok(input);
|
|
97
|
+
}
|
|
98
|
+
if (input.kind !== 'clustered') return invalid('kind');
|
|
99
|
+
if (
|
|
100
|
+
!('transport' in candidate) ||
|
|
101
|
+
candidate.transport === null ||
|
|
102
|
+
typeof candidate.transport !== 'object'
|
|
103
|
+
) {
|
|
104
|
+
return invalid('transport');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const transport = input.transport;
|
|
108
|
+
const requested = prepared.local.length;
|
|
109
|
+
const transportMatchesPrepared =
|
|
110
|
+
transport.layout === prepared.layout &&
|
|
111
|
+
transport.requestedLightCount === requested &&
|
|
112
|
+
transport.admittedLightCount === requested &&
|
|
113
|
+
transport.membershipEntryCount === prepared.membershipEntryCount &&
|
|
114
|
+
transport.lightBoundsBytes === prepared.lightBounds.byteLength;
|
|
115
|
+
const producerMatchesKind =
|
|
116
|
+
(transport.producer === 'gpu' && transport.kind === 'compute-storage') ||
|
|
117
|
+
(transport.producer === 'cpu' && transport.kind === 'cpu-storage');
|
|
118
|
+
if (!transportMatchesPrepared || !producerMatchesKind) return invalid('transport');
|
|
119
|
+
return ok(input);
|
|
120
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
2
|
+
import { type RenderError, StandardClusterTransportUnavailableError } from '../../errors/render';
|
|
3
|
+
import { BYTES_PER_DIRECT_LIGHT_SLOT } from '../../light-buffer-layout';
|
|
4
|
+
import type { PreparedStandardLighting } from './prepare';
|
|
5
|
+
|
|
6
|
+
export interface StandardClusterCapabilities {
|
|
7
|
+
readonly compute: boolean;
|
|
8
|
+
readonly storageBuffer: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* The graph producer is ready to encode the selected compute lane. The
|
|
11
|
+
* renderer supplies this from the actual pipeline + bind-group layout; it is
|
|
12
|
+
* required so capability admission cannot forge a GPU producer from
|
|
13
|
+
* `compute` alone.
|
|
14
|
+
*/
|
|
15
|
+
readonly membershipPipelineReady: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Only transports with storage-backed membership representation exist. */
|
|
19
|
+
export type StandardClusterTransportKind = 'compute-storage' | 'cpu-storage';
|
|
20
|
+
export type StandardClusterMembershipProducer = 'cpu' | 'gpu';
|
|
21
|
+
|
|
22
|
+
export interface StandardClusterTransport {
|
|
23
|
+
readonly kind: StandardClusterTransportKind;
|
|
24
|
+
readonly producer: StandardClusterMembershipProducer;
|
|
25
|
+
readonly layout: PreparedStandardLighting['layout'];
|
|
26
|
+
readonly requestedLightCount: number;
|
|
27
|
+
readonly admittedLightCount: number;
|
|
28
|
+
readonly membershipEntryCount: number;
|
|
29
|
+
readonly occupiedClusterCount: number;
|
|
30
|
+
readonly clusterGridBytes: number;
|
|
31
|
+
readonly lightIndexListBytes: number;
|
|
32
|
+
readonly lightDataBytes: number;
|
|
33
|
+
readonly lightBoundsBytes: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function occupiedClusterCount(prepared: PreparedStandardLighting): number {
|
|
37
|
+
let occupied = 0;
|
|
38
|
+
for (let index = 1; index < prepared.clusterGrid.length; index += 2) {
|
|
39
|
+
if ((prepared.clusterGrid[index] ?? 0) > 0) occupied += 1;
|
|
40
|
+
}
|
|
41
|
+
return occupied;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Select a transport from one prepared frame. Capability facts choose only a
|
|
46
|
+
* producer/storage pair; all counts and byte sizes come from that frame.
|
|
47
|
+
*/
|
|
48
|
+
export function selectStandardClusterTransport(
|
|
49
|
+
capabilities: StandardClusterCapabilities,
|
|
50
|
+
prepared: PreparedStandardLighting,
|
|
51
|
+
): Result<StandardClusterTransport, RenderError> {
|
|
52
|
+
const requested = prepared.local.length;
|
|
53
|
+
if (!capabilities.storageBuffer) {
|
|
54
|
+
return err(
|
|
55
|
+
new StandardClusterTransportUnavailableError(
|
|
56
|
+
requested,
|
|
57
|
+
'enable a proven storage-buffer Cluster transport; compute without storage is not a membership path',
|
|
58
|
+
),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const producer: StandardClusterMembershipProducer =
|
|
63
|
+
capabilities.compute && capabilities.membershipPipelineReady ? 'gpu' : 'cpu';
|
|
64
|
+
const kind: StandardClusterTransportKind = producer === 'gpu' ? 'compute-storage' : 'cpu-storage';
|
|
65
|
+
return ok({
|
|
66
|
+
kind,
|
|
67
|
+
producer,
|
|
68
|
+
layout: prepared.layout,
|
|
69
|
+
requestedLightCount: requested,
|
|
70
|
+
admittedLightCount: requested,
|
|
71
|
+
membershipEntryCount: prepared.membershipEntryCount,
|
|
72
|
+
occupiedClusterCount: occupiedClusterCount(prepared),
|
|
73
|
+
clusterGridBytes: prepared.layout.clusterGridU32Length * Uint32Array.BYTES_PER_ELEMENT,
|
|
74
|
+
lightIndexListBytes: prepared.membershipEntryCount * Uint32Array.BYTES_PER_ELEMENT,
|
|
75
|
+
lightDataBytes: requested * BYTES_PER_DIRECT_LIGHT_SLOT,
|
|
76
|
+
lightBoundsBytes: prepared.lightBounds.byteLength,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
GraphAccess,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
RenderGraphBuilder,
|
|
1
|
+
import {
|
|
2
|
+
type GraphAccess,
|
|
3
|
+
type GraphTextureDescriptor,
|
|
4
|
+
type RenderGraphBuilder,
|
|
6
5
|
RenderGraphError,
|
|
7
6
|
} from '@forgeax/engine-render-graph';
|
|
8
7
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
9
|
-
import {
|
|
8
|
+
import { SceneDataUnavailableError, StandardProfileInvalidError } from '../errors/render';
|
|
10
9
|
import type { FramePlan } from '../extract/environment';
|
|
11
|
-
import {
|
|
12
|
-
GPU_BUFFER_USAGE_COPY_DST,
|
|
13
|
-
GPU_BUFFER_USAGE_STORAGE,
|
|
14
|
-
GPU_BUFFER_USAGE_UNIFORM,
|
|
15
|
-
} from '../gpu-usage';
|
|
16
|
-
import { getOrCreateHdrpBuffers, type HdrpBuffers } from '../hdrp-buffers';
|
|
17
10
|
import { DEFERRED_COLOR_FORMATS } from '../pipeline-spec';
|
|
18
|
-
import type { _InternalRenderPipelineContext } from '../record/render-context';
|
|
19
11
|
import type {
|
|
20
12
|
RenderPipeline,
|
|
21
13
|
RenderPipelineBuildContext,
|
|
@@ -48,16 +40,20 @@ import {
|
|
|
48
40
|
} from '../typed-render-graph-primitives';
|
|
49
41
|
import { addTypedShadowPasses } from '../typed-shadow-passes';
|
|
50
42
|
import { addAuthoredVolumetricFogPasses } from '../volume/passes';
|
|
51
|
-
|
|
52
43
|
import { buildStandardForwardLane } from './standard-forward-lane';
|
|
44
|
+
import {
|
|
45
|
+
addStandardClusterMembershipPass,
|
|
46
|
+
importStandardClusterBuffers,
|
|
47
|
+
standardClusterReadAccesses,
|
|
48
|
+
} from './standard-lighting/graph';
|
|
49
|
+
import {
|
|
50
|
+
deriveStandardTopologyInput,
|
|
51
|
+
type StandardTopologyInputValue,
|
|
52
|
+
} from './standard-lighting/topology';
|
|
53
53
|
import { addStandardPost } from './standard-post';
|
|
54
54
|
import {
|
|
55
|
-
CLUSTER_GRID_STRIDE_U32,
|
|
56
|
-
DEFAULT_CLUSTER_GRID,
|
|
57
55
|
DEFAULT_STANDARD_PROFILE,
|
|
58
|
-
|
|
59
|
-
MAX_LIGHTS,
|
|
60
|
-
resolveStandardLane,
|
|
56
|
+
STANDARD_LIGHT_COUNTS,
|
|
61
57
|
STANDARD_PIPELINE_ID,
|
|
62
58
|
type StandardProfile,
|
|
63
59
|
} from './standard-profile';
|
|
@@ -125,26 +121,11 @@ fn cs_cluster_membership(@builtin(global_invocation_id) global_id : vec3<u32>) {
|
|
|
125
121
|
}
|
|
126
122
|
}
|
|
127
123
|
`;
|
|
128
|
-
export class HdrpInstallError extends Error {
|
|
129
|
-
readonly code = 'hdrp-grid-invalid' as const;
|
|
130
|
-
readonly expected = 'clusterGrid.{x,y,z} each integer in [1, 64]';
|
|
131
|
-
readonly hint: string;
|
|
132
|
-
readonly detail: { readonly x: number; readonly y: number; readonly z: number };
|
|
133
|
-
|
|
134
|
-
constructor(x: number, y: number, z: number) {
|
|
135
|
-
const hint = `clusterGrid {x:${x}, y:${y}, z:${z}} is invalid; set {x,y,z} to positive integers in [1, 64]`;
|
|
136
|
-
super(`hdrp-grid-invalid: ${hint}`);
|
|
137
|
-
this.name = 'HdrpInstallError';
|
|
138
|
-
this.hint = hint;
|
|
139
|
-
this.detail = { x, y, z };
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
124
|
export function validateClusterGrid(grid: {
|
|
144
125
|
x: number;
|
|
145
126
|
y: number;
|
|
146
127
|
z: number;
|
|
147
|
-
}): Result<{ x: number; y: number; z: number },
|
|
128
|
+
}): Result<{ x: number; y: number; z: number }, StandardProfileInvalidError> {
|
|
148
129
|
const { x, y, z } = grid;
|
|
149
130
|
return Number.isInteger(x) &&
|
|
150
131
|
Number.isInteger(y) &&
|
|
@@ -156,7 +137,12 @@ export function validateClusterGrid(grid: {
|
|
|
156
137
|
z >= 1 &&
|
|
157
138
|
z <= 64
|
|
158
139
|
? ok({ x, y, z })
|
|
159
|
-
: err(
|
|
140
|
+
: err(
|
|
141
|
+
new StandardProfileInvalidError(
|
|
142
|
+
`clusterGrid {x:${x}, y:${y}, z:${z}} is invalid; set x, y, and z to positive integers in [1, 64]`,
|
|
143
|
+
{ field: 'clusterGrid', actual: { x, y, z } },
|
|
144
|
+
),
|
|
145
|
+
);
|
|
160
146
|
}
|
|
161
147
|
|
|
162
148
|
function target(
|
|
@@ -167,114 +153,20 @@ function target(
|
|
|
167
153
|
return createRenderPipelineTarget(graph, label, descriptor);
|
|
168
154
|
}
|
|
169
155
|
|
|
170
|
-
|
|
171
|
-
readonly lightData: GraphBuffer;
|
|
172
|
-
readonly clusterGrid: GraphBuffer;
|
|
173
|
-
readonly lightIndexList: GraphBuffer;
|
|
174
|
-
readonly clusterUniform: GraphBuffer;
|
|
175
|
-
readonly lightBounds: GraphBuffer;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function importBuffers(
|
|
179
|
-
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
180
|
-
topology: RenderPipelineTopology,
|
|
181
|
-
): Result<HdrpGraphBuffers, RenderGraphError> {
|
|
182
|
-
const grid = topology.config?.clusterGrid ?? DEFAULT_CLUSTER_GRID;
|
|
183
|
-
const cells = grid.x * grid.y * grid.z;
|
|
184
|
-
const storage = topology.lane.storageBuffer;
|
|
185
|
-
const usage =
|
|
186
|
-
(storage ? GPU_BUFFER_USAGE_STORAGE : GPU_BUFFER_USAGE_UNIFORM) | GPU_BUFFER_USAGE_COPY_DST;
|
|
187
|
-
const resolve = (frame: RenderPipelineFrame): HdrpBuffers => {
|
|
188
|
-
const internal = frame as _InternalRenderPipelineContext;
|
|
189
|
-
const buffers = getOrCreateHdrpBuffers(internal.runtime, grid);
|
|
190
|
-
if (buffers === null) throw new Error('HDRP persistent buffer allocation failed');
|
|
191
|
-
return buffers;
|
|
192
|
-
};
|
|
193
|
-
const lightData = graph.importBuffer(
|
|
194
|
-
'hdrp-light-data',
|
|
195
|
-
{ size: (storage ? MAX_LIGHTS : 128) * 64, usage },
|
|
196
|
-
(frame) => resolve(frame).lightDataBuffer,
|
|
197
|
-
);
|
|
198
|
-
if (!lightData.ok) return lightData;
|
|
199
|
-
const clusterGrid = graph.importBuffer(
|
|
200
|
-
'hdrp-cluster-grid',
|
|
201
|
-
{ size: storage ? cells * CLUSTER_GRID_STRIDE_U32 * 4 : 32, usage },
|
|
202
|
-
(frame) => resolve(frame).clusterGridBuffer,
|
|
203
|
-
);
|
|
204
|
-
if (!clusterGrid.ok) return clusterGrid;
|
|
205
|
-
const lightIndexList = graph.importBuffer(
|
|
206
|
-
'hdrp-light-index-list',
|
|
207
|
-
{ size: storage ? LIGHT_INDEX_LIST_CAPACITY * 4 : 32, usage },
|
|
208
|
-
(frame) => resolve(frame).lightIndexListBuffer,
|
|
209
|
-
);
|
|
210
|
-
if (!lightIndexList.ok) return lightIndexList;
|
|
211
|
-
const clusterUniform = graph.importBuffer(
|
|
212
|
-
'hdrp-cluster-uniform',
|
|
213
|
-
{ size: 32, usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST },
|
|
214
|
-
(frame) => resolve(frame).clusterUniformBuffer,
|
|
215
|
-
);
|
|
216
|
-
if (!clusterUniform.ok) return clusterUniform;
|
|
217
|
-
const lightBounds = graph.importBuffer(
|
|
218
|
-
'hdrp-light-bounds',
|
|
219
|
-
{ size: MAX_LIGHTS * 6 * 4, usage },
|
|
220
|
-
(frame) => resolve(frame).lightBoundsBuffer,
|
|
221
|
-
);
|
|
222
|
-
if (!lightBounds.ok) return lightBounds;
|
|
223
|
-
return ok({
|
|
224
|
-
lightData: lightData.value,
|
|
225
|
-
clusterGrid: clusterGrid.value,
|
|
226
|
-
lightIndexList: lightIndexList.value,
|
|
227
|
-
clusterUniform: clusterUniform.value,
|
|
228
|
-
lightBounds: lightBounds.value,
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function addMembershipPass(
|
|
233
|
-
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
234
|
-
topology: RenderPipelineTopology,
|
|
235
|
-
buffers: HdrpGraphBuffers,
|
|
236
|
-
): Result<void, RenderGraphError> {
|
|
237
|
-
if (!topology.lane.compute || !topology.lane.storageBuffer) return ok(undefined);
|
|
238
|
-
return graph.addComputePass('cluster-membership-producer', {
|
|
239
|
-
accesses: [
|
|
240
|
-
{ resource: buffers.clusterGrid, usage: 'storage-read' },
|
|
241
|
-
{ resource: buffers.clusterUniform, usage: 'uniform-read' },
|
|
242
|
-
{ resource: buffers.lightBounds, usage: 'storage-read' },
|
|
243
|
-
{ resource: buffers.lightIndexList, usage: 'storage-write' },
|
|
244
|
-
],
|
|
245
|
-
executeIf: (frame) => {
|
|
246
|
-
const internal = frame as _InternalRenderPipelineContext;
|
|
247
|
-
return (
|
|
248
|
-
internal.pipelineState.hdrpClusterMembershipPipeline !== null &&
|
|
249
|
-
internal.hdrpClusterMembershipBindGroup !== null
|
|
250
|
-
);
|
|
251
|
-
},
|
|
252
|
-
encode: ({ pass, frame }) => {
|
|
253
|
-
const internal = frame as _InternalRenderPipelineContext;
|
|
254
|
-
const pipeline = internal.pipelineState.hdrpClusterMembershipPipeline;
|
|
255
|
-
const bindings = internal.hdrpClusterMembershipBindGroup;
|
|
256
|
-
if (pipeline === null || bindings === null) return;
|
|
257
|
-
const grid = topology.config?.clusterGrid ?? DEFAULT_CLUSTER_GRID;
|
|
258
|
-
pass.setPipeline(pipeline);
|
|
259
|
-
pass.setBindGroup(0, bindings);
|
|
260
|
-
pass.dispatchWorkgroups(Math.ceil((grid.x * grid.y * grid.z) / 64));
|
|
261
|
-
},
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
function buildHdrp(
|
|
156
|
+
function buildStandardDeferredLane(
|
|
266
157
|
context: RenderPipelineBuildContext<RenderPipelineFrame>,
|
|
267
158
|
topology: RenderPipelineTopology,
|
|
159
|
+
lighting: StandardTopologyInputValue,
|
|
268
160
|
): ReturnType<RenderPipeline['build']> {
|
|
269
|
-
if (topology.lane.maxColorAttachments < 4) {
|
|
270
|
-
return err(new HdrpDeferredCapsInsufficientError(topology.lane.maxColorAttachments));
|
|
271
|
-
}
|
|
272
161
|
const graph = context.graph;
|
|
273
162
|
const surface = importRenderPipelineSurface(graph, topology);
|
|
274
163
|
if (!surface.ok) return surface;
|
|
275
|
-
const buffers =
|
|
164
|
+
const buffers = importStandardClusterBuffers(graph, lighting);
|
|
276
165
|
if (!buffers.ok) return buffers;
|
|
277
|
-
const membership =
|
|
166
|
+
const membership =
|
|
167
|
+
buffers.value === null
|
|
168
|
+
? ok(undefined)
|
|
169
|
+
: addStandardClusterMembershipPass(graph, lighting, buffers.value);
|
|
278
170
|
if (!membership.ok) return membership;
|
|
279
171
|
const shadows = addTypedShadowPasses(graph, topology);
|
|
280
172
|
if (!shadows.ok) return shadows;
|
|
@@ -305,9 +197,7 @@ function buildHdrp(
|
|
|
305
197
|
taa: topology.camera.antialias === 'taa',
|
|
306
198
|
motionBlur: topology.temporal?.motionBlur === true,
|
|
307
199
|
});
|
|
308
|
-
const temporalLane = topology.lane.compute
|
|
309
|
-
? (topology.standardProfile?.lighting ?? 'direct')
|
|
310
|
-
: 'cpu-webgl2';
|
|
200
|
+
const temporalLane = topology.lane.compute ? 'clustered' : 'cpu-webgl2';
|
|
311
201
|
const temporalAdmission = standardTemporalLaneAdmission({
|
|
312
202
|
lane: temporalLane,
|
|
313
203
|
demand: temporalDemand,
|
|
@@ -330,7 +220,11 @@ function buildHdrp(
|
|
|
330
220
|
}),
|
|
331
221
|
);
|
|
332
222
|
}
|
|
333
|
-
|
|
223
|
+
const gpuDriven = context.projectGpuDriven({
|
|
224
|
+
format: scene.value.format,
|
|
225
|
+
sampleCount: scene.value.sampleCount,
|
|
226
|
+
});
|
|
227
|
+
if (!gpuDriven.ok) return gpuDriven;
|
|
334
228
|
const gbuffer = addTypedScenePass(graph, {
|
|
335
229
|
name: 'g-buffer',
|
|
336
230
|
color: gbuffer0.value,
|
|
@@ -363,25 +257,13 @@ function buildHdrp(
|
|
|
363
257
|
{ resource: gbuffer1.value.view, usage: 'sampled-read' },
|
|
364
258
|
{ resource: gbuffer2.value.view, usage: 'sampled-read' },
|
|
365
259
|
{ resource: depth.value.view, usage: 'depth-stencil-read' },
|
|
366
|
-
|
|
367
|
-
resource: buffers.value.lightData,
|
|
368
|
-
usage: topology.lane.storageBuffer ? 'storage-read' : 'uniform-read',
|
|
369
|
-
},
|
|
370
|
-
{
|
|
371
|
-
resource: buffers.value.clusterGrid,
|
|
372
|
-
usage: topology.lane.storageBuffer ? 'storage-read' : 'uniform-read',
|
|
373
|
-
},
|
|
374
|
-
{
|
|
375
|
-
resource: buffers.value.lightIndexList,
|
|
376
|
-
usage: topology.lane.storageBuffer ? 'storage-read' : 'uniform-read',
|
|
377
|
-
},
|
|
378
|
-
{ resource: buffers.value.clusterUniform, usage: 'uniform-read' },
|
|
260
|
+
...(buffers.value === null ? [] : standardClusterReadAccesses(buffers.value)),
|
|
379
261
|
...(ssao === undefined
|
|
380
262
|
? []
|
|
381
263
|
: ([{ resource: ssao.view, usage: 'sampled-read' }] satisfies GraphAccess[])),
|
|
382
264
|
{ resource: scene.value.view, usage: 'color-attachment' },
|
|
383
265
|
];
|
|
384
|
-
const
|
|
266
|
+
const lightingPass = graph.addRasterPass('lighting', {
|
|
385
267
|
accesses: lightingAccesses,
|
|
386
268
|
colorAttachments: [
|
|
387
269
|
{
|
|
@@ -393,7 +275,7 @@ function buildHdrp(
|
|
|
393
275
|
],
|
|
394
276
|
encode: () => undefined,
|
|
395
277
|
});
|
|
396
|
-
if (!
|
|
278
|
+
if (!lightingPass.ok) return lightingPass;
|
|
397
279
|
|
|
398
280
|
const skybox = addTypedSkyboxPass(graph, scene.value);
|
|
399
281
|
if (!skybox.ok) return skybox;
|
|
@@ -403,21 +285,8 @@ function buildHdrp(
|
|
|
403
285
|
demand: transmissionDemand,
|
|
404
286
|
sourceSampleCount: scene.value.sampleCount,
|
|
405
287
|
}).active;
|
|
406
|
-
const forwardExtraAccesses: GraphAccess[] =
|
|
407
|
-
|
|
408
|
-
resource: buffers.value.lightData,
|
|
409
|
-
usage: topology.lane.storageBuffer ? 'storage-read' : 'uniform-read',
|
|
410
|
-
},
|
|
411
|
-
{
|
|
412
|
-
resource: buffers.value.clusterGrid,
|
|
413
|
-
usage: topology.lane.storageBuffer ? 'storage-read' : 'uniform-read',
|
|
414
|
-
},
|
|
415
|
-
{
|
|
416
|
-
resource: buffers.value.lightIndexList,
|
|
417
|
-
usage: topology.lane.storageBuffer ? 'storage-read' : 'uniform-read',
|
|
418
|
-
},
|
|
419
|
-
{ resource: buffers.value.clusterUniform, usage: 'uniform-read' },
|
|
420
|
-
];
|
|
288
|
+
const forwardExtraAccesses: GraphAccess[] =
|
|
289
|
+
buffers.value === null ? [] : [...standardClusterReadAccesses(buffers.value)];
|
|
421
290
|
|
|
422
291
|
const forward = addTypedScenePass(graph, {
|
|
423
292
|
name: 'forward',
|
|
@@ -430,16 +299,20 @@ function buildHdrp(
|
|
|
430
299
|
gbuffer0.value,
|
|
431
300
|
gbuffer1.value,
|
|
432
301
|
gbuffer2.value,
|
|
433
|
-
shadows.value.directional,
|
|
302
|
+
...(shadows.value.directional === undefined ? [] : [shadows.value.directional]),
|
|
434
303
|
shadows.value.spot,
|
|
435
304
|
...(shadows.value.point === undefined ? [] : [shadows.value.point]),
|
|
436
305
|
...(ssao === undefined ? [] : [ssao]),
|
|
437
306
|
],
|
|
438
|
-
|
|
307
|
+
...(shadows.value.directional === undefined
|
|
308
|
+
? {}
|
|
309
|
+
: { directionalShadow: shadows.value.directional }),
|
|
439
310
|
spotShadow: shadows.value.spot,
|
|
440
311
|
...(ssao === undefined ? {} : { ssao }),
|
|
312
|
+
...(gpuDriven.value === undefined ? {} : { gpuDriven: gpuDriven.value }),
|
|
441
313
|
passKind: 'forward',
|
|
442
314
|
...(transmissionActive ? { recordMode: 'opaque' as const } : {}),
|
|
315
|
+
...(context.occlusion === undefined ? {} : { occlusion: context.occlusion }),
|
|
443
316
|
extraAccesses: forwardExtraAccesses,
|
|
444
317
|
});
|
|
445
318
|
if (!forward.ok) return forward;
|
|
@@ -472,7 +345,7 @@ function buildHdrp(
|
|
|
472
345
|
gbuffer0.value,
|
|
473
346
|
gbuffer1.value,
|
|
474
347
|
gbuffer2.value,
|
|
475
|
-
shadows.value.directional,
|
|
348
|
+
...(shadows.value.directional === undefined ? [] : [shadows.value.directional]),
|
|
476
349
|
shadows.value.spot,
|
|
477
350
|
...(shadows.value.point === undefined ? [] : [shadows.value.point]),
|
|
478
351
|
...(ssao === undefined ? [] : [ssao]),
|
|
@@ -501,7 +374,7 @@ function buildHdrp(
|
|
|
501
374
|
gbuffer0.value,
|
|
502
375
|
gbuffer1.value,
|
|
503
376
|
gbuffer2.value,
|
|
504
|
-
shadows.value.directional,
|
|
377
|
+
...(shadows.value.directional === undefined ? [] : [shadows.value.directional]),
|
|
505
378
|
shadows.value.spot,
|
|
506
379
|
...(shadows.value.point === undefined ? [] : [shadows.value.point]),
|
|
507
380
|
...(ssao === undefined ? [] : [ssao]),
|
|
@@ -529,8 +402,9 @@ function buildHdrp(
|
|
|
529
402
|
topology,
|
|
530
403
|
scene.value,
|
|
531
404
|
depthSample.value,
|
|
532
|
-
shadows.value.directional
|
|
405
|
+
shadows.value.directional?.view,
|
|
533
406
|
shadows.value.spot.view,
|
|
407
|
+
buffers.value,
|
|
534
408
|
);
|
|
535
409
|
if (!volume.ok) return volume;
|
|
536
410
|
}
|
|
@@ -556,8 +430,7 @@ function buildHdrp(
|
|
|
556
430
|
if (!features.ok) return features;
|
|
557
431
|
const observation = addTypedFrameObservationPass(graph, scene.value, 'forgeax::standard');
|
|
558
432
|
if (!observation.ok) return observation;
|
|
559
|
-
|
|
560
|
-
return addStandardPost(
|
|
433
|
+
const post = addStandardPost(
|
|
561
434
|
context,
|
|
562
435
|
topology,
|
|
563
436
|
scene.value,
|
|
@@ -565,13 +438,19 @@ function buildHdrp(
|
|
|
565
438
|
surface.value,
|
|
566
439
|
temporal.value?.temporal,
|
|
567
440
|
);
|
|
441
|
+
if (!post.ok) return post;
|
|
442
|
+
const cubeCaptures = context.contributeCubeCaptures?.();
|
|
443
|
+
if (cubeCaptures !== undefined && !cubeCaptures.ok) return cubeCaptures;
|
|
444
|
+
return ok(undefined);
|
|
568
445
|
}
|
|
569
|
-
const buildStandardClusteredLane = buildHdrp;
|
|
570
|
-
|
|
571
446
|
export interface StandardPipeline extends RenderPipeline {
|
|
572
447
|
readonly identity: typeof STANDARD_PIPELINE_ID;
|
|
573
448
|
}
|
|
574
449
|
|
|
450
|
+
export function standardProfileSupportsReflectionProbes(_profile: StandardProfile): boolean {
|
|
451
|
+
return true;
|
|
452
|
+
}
|
|
453
|
+
|
|
575
454
|
/** Standard graph inputs are derived once from the immutable frame plan. */
|
|
576
455
|
export type StandardFramePlan = FramePlan;
|
|
577
456
|
|
|
@@ -579,6 +458,43 @@ function profileFor(topology: RenderPipelineTopology): StandardProfile {
|
|
|
579
458
|
return topology.standardProfile ?? DEFAULT_STANDARD_PROFILE;
|
|
580
459
|
}
|
|
581
460
|
|
|
461
|
+
function resolveStandardTopologyInput(
|
|
462
|
+
context: RenderPipelineBuildContext<RenderPipelineFrame>,
|
|
463
|
+
): Result<StandardTopologyInputValue, RenderGraphError> {
|
|
464
|
+
const supplied = context.standardLighting;
|
|
465
|
+
if (supplied !== undefined) {
|
|
466
|
+
const derived = deriveStandardTopologyInput(supplied);
|
|
467
|
+
if (derived.ok) return derived;
|
|
468
|
+
return err(
|
|
469
|
+
new RenderGraphError({
|
|
470
|
+
code: 'resource-descriptor-invalid',
|
|
471
|
+
expected: 'Forward/Deferred consume one prepared Standard topology input',
|
|
472
|
+
hint: derived.error.hint,
|
|
473
|
+
detail: {
|
|
474
|
+
resourceLabel: 'forgeax::standard',
|
|
475
|
+
field: `standardLighting.${derived.error.detail.field}`,
|
|
476
|
+
expected: derived.error.expected,
|
|
477
|
+
actual: 'invalid',
|
|
478
|
+
},
|
|
479
|
+
}),
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return err(
|
|
484
|
+
new RenderGraphError({
|
|
485
|
+
code: 'resource-descriptor-invalid',
|
|
486
|
+
expected: 'RenderPipelineBuildContext.standardLighting from frame preparation',
|
|
487
|
+
hint: 'prepare Standard lighting once, select a proven Cluster transport, and pass it to both lanes',
|
|
488
|
+
detail: {
|
|
489
|
+
resourceLabel: 'forgeax::standard',
|
|
490
|
+
field: 'standardLighting',
|
|
491
|
+
expected: 'prepared Standard lighting topology input',
|
|
492
|
+
actual: 'invalid',
|
|
493
|
+
},
|
|
494
|
+
}),
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
|
|
582
498
|
function standardTopology(
|
|
583
499
|
topology: RenderPipelineTopology,
|
|
584
500
|
profile: StandardProfile,
|
|
@@ -596,26 +512,41 @@ function standardTopology(
|
|
|
596
512
|
}
|
|
597
513
|
|
|
598
514
|
/**
|
|
599
|
-
* The sole built-in pipeline entry point.
|
|
600
|
-
*
|
|
601
|
-
*
|
|
515
|
+
* The sole built-in pipeline entry point. All local lights use the same
|
|
516
|
+
* prepared Cluster topology; the profile chooses only Forward or Deferred
|
|
517
|
+
* graph shape and never a second lighting authority.
|
|
602
518
|
*/
|
|
603
519
|
function buildStandard(
|
|
604
520
|
context: RenderPipelineBuildContext<RenderPipelineFrame>,
|
|
605
521
|
topology: RenderPipelineTopology,
|
|
606
522
|
): ReturnType<RenderPipeline['build']> {
|
|
607
523
|
const profile = profileFor(topology);
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
524
|
+
if (!STANDARD_LIGHT_COUNTS.some((count) => count === profile.lightCount)) {
|
|
525
|
+
return err(
|
|
526
|
+
new RenderGraphError({
|
|
527
|
+
code: 'resource-descriptor-invalid',
|
|
528
|
+
expected: 'StandardProfile.lightCount is one of 1, 32, or 256',
|
|
529
|
+
hint: 'set StandardProfile.lightCount to 1, 32, or 256',
|
|
530
|
+
detail: {
|
|
531
|
+
resourceLabel: 'forgeax::standard',
|
|
532
|
+
field: 'lightCount',
|
|
533
|
+
expected: '1 | 32 | 256',
|
|
534
|
+
actual: profile.lightCount,
|
|
535
|
+
},
|
|
536
|
+
}),
|
|
537
|
+
);
|
|
538
|
+
}
|
|
612
539
|
const effective = standardTopology(topology, profile);
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
//
|
|
616
|
-
|
|
617
|
-
if (
|
|
618
|
-
|
|
540
|
+
const lighting = resolveStandardTopologyInput(context);
|
|
541
|
+
if (!lighting.ok) return lighting;
|
|
542
|
+
// A missing Camera is an intentional clear-only frame. Keep it on the
|
|
543
|
+
// forward raster lane so clustered resources cannot introduce work.
|
|
544
|
+
if (effective.clearOnly === true) {
|
|
545
|
+
return buildStandardForwardLane(context, effective, lighting.value);
|
|
546
|
+
}
|
|
547
|
+
return profile.renderPath === 'forward'
|
|
548
|
+
? buildStandardForwardLane(context, effective, lighting.value)
|
|
549
|
+
: buildStandardDeferredLane(context, effective, lighting.value);
|
|
619
550
|
}
|
|
620
551
|
|
|
621
552
|
export const standardPipeline: StandardPipeline = Object.freeze({
|