@forgeax/engine-render 0.1.21 → 0.1.24
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 +281 -38
- package/dist/assembly/backend-contract.d.ts +13 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/bundler-contract.d.ts +9 -0
- package/dist/assembly/bundler-contract.d.ts.map +1 -0
- package/dist/assembly/device-feature-admission.d.ts +8 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -1
- package/dist/assembly/extended-lighting-fallback.d.ts +13 -0
- package/dist/assembly/extended-lighting-fallback.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +7 -235
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +10 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +3 -2
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/standard-layer-projection.d.ts +10 -0
- package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -0
- package/dist/assembly/material-shader-policy.d.ts +168 -0
- package/dist/assembly/material-shader-policy.d.ts.map +1 -0
- package/dist/assembly/material-shader-prewarm.d.ts +21 -0
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/mesh-ssbo-grow.d.ts +88 -0
- package/dist/assembly/mesh-ssbo-grow.d.ts.map +1 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts +14 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -0
- package/dist/assembly/recovery/generation.d.ts +46 -0
- package/dist/assembly/recovery/generation.d.ts.map +1 -0
- package/dist/assembly/recovery/recovery-attempt.d.ts +63 -0
- package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts +115 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -0
- package/dist/assembly/renderer-facade.d.ts +10 -0
- package/dist/assembly/renderer-facade.d.ts.map +1 -0
- package/dist/assembly/renderer-frame-transaction.d.ts +17 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-helpers.d.ts +19 -0
- package/dist/assembly/renderer-helpers.d.ts.map +1 -0
- package/dist/assembly/renderer-lifecycle.d.ts +34 -0
- package/dist/assembly/renderer-lifecycle.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +15 -0
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready-contract.d.ts +9 -0
- package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +55 -0
- package/dist/assembly/webgpu-ready.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +152 -0
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -0
- package/dist/authoring.mjs +1 -1
- package/dist/{chunk-PCHBPYML.mjs → chunk-GE3SDD72.mjs} +37 -5
- package/dist/chunk-GE3SDD72.mjs.map +1 -0
- package/dist/chunk-KZFTK6DO.mjs +1191 -0
- package/dist/chunk-KZFTK6DO.mjs.map +1 -0
- package/dist/{chunk-FS2KNUQH.mjs → chunk-Q752SHI5.mjs} +332 -568
- package/dist/chunk-Q752SHI5.mjs.map +1 -0
- package/dist/{chunk-6OPXDQ2E.mjs → chunk-RR5L4SRS.mjs} +33 -294
- package/dist/chunk-RR5L4SRS.mjs.map +1 -0
- package/dist/chunk-TFH5I7JJ.mjs +296 -0
- package/dist/chunk-TFH5I7JJ.mjs.map +1 -0
- package/dist/chunk-UQYS7FRM.mjs +1003 -0
- package/dist/chunk-UQYS7FRM.mjs.map +1 -0
- package/dist/chunk-YKB5DQV7.mjs +345 -0
- package/dist/chunk-YKB5DQV7.mjs.map +1 -0
- package/dist/{chunk-5YADUCA7.mjs → chunk-YRUYGA4A.mjs} +1189 -1217
- package/dist/chunk-YRUYGA4A.mjs.map +1 -0
- package/dist/chunk-Z3YYH2MB.mjs +5082 -0
- package/dist/chunk-Z3YYH2MB.mjs.map +1 -0
- package/dist/cluster-binner.d.ts +5 -0
- package/dist/cluster-binner.d.ts.map +1 -1
- package/dist/components/index.d.ts +3 -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/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 +27276 -23232
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/device-scope.d.ts +2 -0
- package/dist/device/device-scope.d.ts.map +1 -1
- package/dist/device/gpu-residency.d.ts +32 -5
- 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 +5 -0
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/inspection.d.ts +7 -0
- package/dist/environment/inspection.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +20 -2
- 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 +67 -3
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +39 -1
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +899 -0
- package/dist/extract/contracts.d.ts.map +1 -0
- 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/host.d.ts +2 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +3 -0
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics-store.d.ts +2 -0
- package/dist/features/prepared-graphics-store.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 +126 -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 +9 -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 +3 -3
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +7 -6
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +7 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +90 -5
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +163 -1
- package/dist/inspection-types.d.ts.map +1 -1
- 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 +60 -148
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts +34 -10
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +56 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/occlusion-proxy.d.ts +4 -0
- package/dist/occlusion-proxy.d.ts.map +1 -0
- package/dist/pbr-pipeline.d.ts +58 -21
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/light-frame.d.ts +3 -3
- package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/topology.d.ts +1 -1
- package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.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 +1 -1
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/points-lines/prepare.d.ts +3 -0
- package/dist/points-lines/prepare.d.ts.map +1 -1
- package/dist/points-lines/standard-owner.d.ts +33 -0
- package/dist/points-lines/standard-owner.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 +8 -6
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +55 -10
- 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 +21 -5
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-timing.d.ts +19 -7
- 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 +20 -2
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +10 -18
- 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.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +11 -3
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/recovery-pipeline.d.ts +30 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -0
- package/dist/record/render-context.d.ts +82 -9
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +49 -2
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +1 -2
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +65 -0
- package/dist/recovery/render-system-candidate.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 +49 -0
- package/dist/reflection/projection.d.ts.map +1 -1
- 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 +78 -15
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +7 -0
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +12 -0
- package/dist/render-system-extract-tail.d.ts.map +1 -0
- package/dist/render-system-extract.d.ts +252 -30
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +140 -5
- package/dist/render-system.d.ts.map +1 -1
- 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 +122 -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/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/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/taa-history-store.d.ts +15 -1
- package/dist/temporal/taa-history-store.d.ts.map +1 -1
- package/dist/temporal/transaction.d.ts +5 -0
- package/dist/temporal/transaction.d.ts.map +1 -1
- 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 +4 -0
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +8 -4
- package/dist/volume/passes.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +5 -0
- package/src/__tests__/detached-inspection.integration.test.ts +6 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +19 -1
- package/src/__tests__/device-loss-fanout.unit.test.ts +107 -0
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +21 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +59 -3
- package/src/__tests__/environment-generation.integration.test.ts +39 -0
- package/src/__tests__/evidence-identity.ts +13 -0
- package/src/__tests__/evidence-identity.unit.test.ts +24 -0
- package/src/__tests__/expose-renderer-errors.unit.test.ts +34 -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 +154 -6
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +4 -1
- package/src/__tests__/frame-observation.contract.test.ts +15 -0
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +1 -0
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +1 -0
- package/src/__tests__/gpu-driven-production.integration.test.ts +572 -9
- 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 +89 -2
- 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-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__/ibl/face-uniforms.unit.test.ts +2 -0
- package/src/__tests__/ibl-residency-publication.unit.test.ts +113 -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 +41 -9
- package/src/__tests__/material-cooked-projection.unit.test.ts +19 -1
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +29 -0
- package/src/__tests__/material-stride-surface.unit.test.ts +7 -3
- package/src/__tests__/materials-standard-contract.unit.test.ts +104 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
- 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__/physical-clearcoat.integration.test.ts +89 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +1 -1
- 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__/recover-error-policy-owner.unit.test.ts +6 -3
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +140 -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-owner-placement.unit.test.ts +39 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
- 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__/renderer-factory-material-contract.unit.test.ts +160 -17
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +47 -0
- package/src/__tests__/renderer-generation-assembly.unit.test.ts +77 -0
- package/src/__tests__/renderer-generation-failure.unit.test.ts +108 -0
- package/src/__tests__/renderer-producer-root-matrix.integration.test.ts +33 -0
- package/src/__tests__/renderer-recovery-capability-matrix.unit.test.ts +59 -0
- package/src/__tests__/renderer-recovery-contract.unit.test.ts +73 -0
- package/src/__tests__/renderer-recovery-lifecycle.unit.test.ts +216 -0
- package/src/__tests__/renderer-target-history-recovery.integration.test.ts +80 -0
- package/src/__tests__/shader-manifest-fixture.ts +13 -16
- package/src/__tests__/shader-stage-surface.unit.test.ts +1 -1
- package/src/__tests__/skin-motion-regression.unit.test.ts +22 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +2 -2
- 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-variant-resolution.unit.test.ts +67 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +7 -0
- package/src/__tests__/standard-layer-projection.unit.test.ts +23 -0
- package/src/__tests__/standard-lighting-inspection.integration.test.ts +1 -1
- package/src/__tests__/standard-lighting-write.unit.test.ts +66 -2
- 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 +111 -32
- 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__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +3 -1
- package/src/assembly/backend-contract.ts +13 -0
- package/src/assembly/bundler-contract.ts +9 -0
- package/src/assembly/device-feature-admission.ts +26 -9
- package/src/assembly/extended-lighting-fallback.ts +216 -0
- package/src/assembly/factory.ts +81 -9634
- package/src/assembly/host-contract.ts +10 -0
- package/src/assembly/material/assembly.ts +18 -2
- package/src/assembly/material/standard-layer-projection.ts +16 -0
- package/src/assembly/material-shader-policy.ts +854 -0
- package/src/assembly/material-shader-prewarm.ts +88 -0
- package/src/assembly/mesh-ssbo-grow.ts +270 -0
- package/src/assembly/recovery/device-loss-fanout.ts +89 -0
- package/src/assembly/recovery/generation.ts +141 -0
- package/src/assembly/recovery/recovery-attempt.ts +800 -0
- package/src/assembly/recovery/renderer-recover.ts +906 -0
- package/src/assembly/renderer-facade.ts +342 -0
- package/src/assembly/renderer-frame-transaction.ts +45 -0
- package/src/assembly/renderer-helpers.ts +99 -0
- package/src/assembly/renderer-lifecycle.ts +159 -0
- package/src/assembly/shader-prewarm-policy.ts +157 -0
- package/src/assembly/webgpu-ready-contract.ts +14 -0
- package/src/assembly/webgpu-ready.ts +4079 -0
- package/src/assembly/webgpu-renderer.ts +4095 -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/camera.ts +1 -1
- package/src/components/index.ts +3 -0
- package/src/components/light-helpers.ts +52 -1
- package/src/components/light-probe.ts +13 -0
- package/src/components/rect-area-light.ts +15 -0
- package/src/components/scene-instance.ts +6 -0
- package/src/components/spot-light.ts +3 -0
- package/src/debug-draw-glue.ts +1 -1
- package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
- package/src/device/device-scope.ts +35 -6
- package/src/device/gpu-residency.ts +334 -35
- package/src/device/lifecycle-transaction.ts +12 -0
- package/src/environment/frame.ts +6 -0
- package/src/environment/inspection.ts +10 -0
- package/src/environment/lifecycle.ts +122 -9
- package/src/errors/gpu-driven.ts +92 -0
- package/src/errors/index.ts +1 -0
- package/src/errors/recover.ts +108 -5
- package/src/errors/render.ts +72 -1
- package/src/extract/camera.ts +3 -3
- package/src/extract/contracts.ts +974 -0
- package/src/extract/gpu-driven.ts +108 -0
- package/src/extract/visibility.ts +0 -23
- package/src/features/host.ts +16 -0
- package/src/features/prepared-gpu-work.ts +20 -2
- package/src/features/prepared-graphics-store.ts +17 -0
- package/src/gpu-driven/batch-topology.ts +206 -28
- package/src/gpu-driven/prepared-draw.ts +208 -0
- package/src/gpu-driven/production-raster.ts +1046 -39
- package/src/gpu-driven/view-gpu.ts +411 -29
- package/src/gpu-scene-schema.ts +13 -0
- package/src/gpu-scene.ts +137 -67
- package/src/gpu-usage.ts +0 -1
- package/src/hdrp-buffers.ts +6 -6
- package/src/ibl/IblPipelineCache.ts +134 -50
- package/src/ibl/skylight-bind-group.ts +26 -0
- package/src/index.ts +83 -1
- package/src/inspection-types.ts +220 -1
- package/src/internal.ts +38 -0
- package/src/light-buffer-layout.ts +157 -324
- package/src/materials.ts +278 -47
- package/src/mesh-material-bindings.ts +59 -0
- package/src/occlusion-proxy.ts +64 -0
- package/src/pbr-pipeline.ts +290 -60
- package/src/pipeline/standard-forward-lane.ts +47 -0
- package/src/pipeline/standard-lighting/graph.ts +2 -1
- package/src/pipeline/standard-lighting/light-frame.ts +3 -2
- package/src/pipeline/standard-lighting/topology.ts +1 -1
- package/src/pipeline/standard-lighting/transport.ts +2 -1
- package/src/pipeline/standard-pipeline.ts +2 -0
- package/src/pipeline-builder.ts +5 -2
- package/src/pipeline-spec.ts +12 -1
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/cache-recovery.unit.test.ts +22 -0
- package/src/points-lines/prepare.ts +9 -0
- package/src/points-lines/standard-owner.ts +403 -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__/frame-targets-recovery.unit.test.ts +60 -0
- package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +26 -1
- package/src/record/__tests__/mesh-ssbo.unit.test.ts +38 -0
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +124 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +28 -13
- package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +47 -4
- package/src/record/__tests__/temporal-payload.unit.test.ts +29 -28
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +21 -2
- package/src/record/frame-lighting.ts +252 -53
- package/src/record/frame-snapshot.ts +72 -12
- package/src/record/frame-targets.ts +11 -1
- package/src/record/frame.ts +416 -95
- package/src/record/gpu-timing.ts +108 -44
- package/src/record/helpers.ts +1 -59
- package/src/record/main-pass-geometry.ts +434 -44
- package/src/record/main-pass-material.ts +324 -210
- package/src/record/main-pass-sprite-draws.ts +58 -92
- package/src/record/main-pass.ts +94 -6
- package/src/record/mesh-ssbo.ts +79 -46
- package/src/record/recovery-pipeline.ts +695 -0
- package/src/record/render-context.ts +99 -7
- package/src/record/shadow-pass.ts +66 -40
- package/src/record/typed-frame-graph.ts +270 -84
- package/src/record/view-ubo.ts +17 -27
- package/src/recovery/render-system-candidate.ts +839 -0
- package/src/reflection/inspection.ts +67 -0
- package/src/reflection/projection.ts +196 -1
- package/src/reflection/record-owner.ts +1283 -0
- package/src/render-contract.ts +82 -12
- package/src/render-pipeline.ts +5 -0
- package/src/render-system-extract-tail.ts +2983 -0
- package/src/render-system-extract.ts +290 -2784
- package/src/render-system.ts +1597 -1192
- 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 +972 -184
- 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/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/temporal/frame-coordinator.ts +30 -1
- package/src/temporal/frame.ts +14 -1
- package/src/temporal/taa-history-store.ts +46 -2
- package/src/temporal/temporal-view.ts +1 -1
- package/src/temporal/transaction.ts +9 -0
- package/src/temporal/view.ts +11 -0
- package/src/tilemap-chunk-extract-system.ts +5 -5
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +19 -12
- package/src/typed-render-graph-primitives.ts +48 -0
- package/src/volume/passes.ts +46 -49
- package/dist/.tsbuildinfo +0 -1
- package/dist/chunk-5YADUCA7.mjs.map +0 -1
- package/dist/chunk-6OPXDQ2E.mjs.map +0 -1
- package/dist/chunk-BXBQQKFQ.mjs +0 -67
- package/dist/chunk-BXBQQKFQ.mjs.map +0 -1
- package/dist/chunk-FS2KNUQH.mjs.map +0 -1
- package/dist/chunk-PCHBPYML.mjs.map +0 -1
- package/dist/chunk-VFPLTKCU.mjs +0 -192
- package/dist/chunk-VFPLTKCU.mjs.map +0 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { MaterialShaderArtifact } from '@forgeax/engine-shader';
|
|
2
|
+
import type { MeshAsset } from '@forgeax/engine-types';
|
|
3
|
+
import {
|
|
4
|
+
type GpuDrivenDrawRange,
|
|
5
|
+
type PreparedGpuDrivenDraw,
|
|
6
|
+
type PrepareGpuDrivenDrawInput,
|
|
7
|
+
prepareGpuDrivenDraw,
|
|
8
|
+
} from '../gpu-driven/prepared-draw';
|
|
9
|
+
import type { MaterialSnapshot } from '../render-system-extract';
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
GpuDrivenPreparationError,
|
|
13
|
+
type GpuDrivenPreparationErrorCode,
|
|
14
|
+
type GpuDrivenPreparationErrorDetail,
|
|
15
|
+
type GpuDrivenPreparationReason,
|
|
16
|
+
} from '../errors/gpu-driven';
|
|
17
|
+
export {
|
|
18
|
+
type GpuDrivenDrawRange,
|
|
19
|
+
type GpuDrivenGeometryReceipt,
|
|
20
|
+
type GpuDrivenSkinReceipt,
|
|
21
|
+
type PreparedGpuDrivenDraw,
|
|
22
|
+
type PrepareGpuDrivenDrawInput,
|
|
23
|
+
prepareGpuDrivenDraw,
|
|
24
|
+
} from '../gpu-driven/prepared-draw';
|
|
25
|
+
|
|
26
|
+
export interface GpuDrivenDrawSnapshot {
|
|
27
|
+
readonly kind: GpuDrivenDrawRange['kind'];
|
|
28
|
+
readonly first: GpuDrivenDrawRange['first'];
|
|
29
|
+
readonly count: GpuDrivenDrawRange['count'];
|
|
30
|
+
readonly baseVertex: GpuDrivenDrawRange['baseVertex'];
|
|
31
|
+
readonly materialSlot: number;
|
|
32
|
+
readonly topology: GpuDrivenDrawRange['topology'];
|
|
33
|
+
readonly pipelineClass: string;
|
|
34
|
+
readonly materialResourceClass: string;
|
|
35
|
+
/** Producer-owned prepared ABI facts used by the PBR GPU lane. */
|
|
36
|
+
readonly prepared?: PreparedGpuDrivenDraw;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Resolves prepared facts once at extract time; record never re-reads assets.
|
|
41
|
+
* The resolver surfaces UV, reflection, vertex, alpha, resource, and
|
|
42
|
+
* generation failures as GpuDrivenPreparationError before recording.
|
|
43
|
+
*/
|
|
44
|
+
export function resolvePreparedGpuDrivenDraw(input: PrepareGpuDrivenDrawInput):
|
|
45
|
+
| { readonly ok: true; readonly value: PreparedGpuDrivenDraw }
|
|
46
|
+
| {
|
|
47
|
+
readonly ok: false;
|
|
48
|
+
readonly error: import('../errors/gpu-driven').GpuDrivenPreparationError;
|
|
49
|
+
} {
|
|
50
|
+
return prepareGpuDrivenDraw(input);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Keeps the artifact type visible at this owner boundary for contract checks. */
|
|
54
|
+
export type PreparedGpuDrivenArtifact = MaterialShaderArtifact;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Derives the resource identity consumed by the existing GPU-driven batch
|
|
58
|
+
* owner. The extract stage is the only place that resolves material values;
|
|
59
|
+
* this helper keeps the batch adapter from re-reading assets later.
|
|
60
|
+
*/
|
|
61
|
+
export function gpuDrivenMaterialResourceClass(material: MaterialSnapshot): string {
|
|
62
|
+
const textures = [...(material.textureHandles?.entries() ?? [])]
|
|
63
|
+
.map(([name, handle]) => [name, Number(handle)] as const)
|
|
64
|
+
.sort(([left], [right]) => left.localeCompare(right));
|
|
65
|
+
const samplers = [...(material.samplerHandles?.entries() ?? [])]
|
|
66
|
+
.map(([name, handle]) => [name, Number(handle)] as const)
|
|
67
|
+
.sort(([left], [right]) => left.localeCompare(right));
|
|
68
|
+
return JSON.stringify({
|
|
69
|
+
textures,
|
|
70
|
+
samplers,
|
|
71
|
+
video: [...(material.videoTextureFields?.keys() ?? [])].sort(),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Projects already-resolved mesh facts into the existing GPU-driven draw
|
|
77
|
+
* snapshot. No World or AssetRegistry access is permitted at this boundary.
|
|
78
|
+
*/
|
|
79
|
+
export function buildGpuDrivenDraws(input: {
|
|
80
|
+
readonly submeshes: readonly MeshAsset['submeshes'][number][];
|
|
81
|
+
readonly indexed: boolean;
|
|
82
|
+
readonly materials: readonly MaterialSnapshot[];
|
|
83
|
+
readonly fallbackMaterial: MaterialSnapshot;
|
|
84
|
+
readonly prepare?: (
|
|
85
|
+
draw: GpuDrivenDrawSnapshot,
|
|
86
|
+
material: MaterialSnapshot,
|
|
87
|
+
) => PreparedGpuDrivenDraw | undefined;
|
|
88
|
+
}): GpuDrivenDrawSnapshot[] {
|
|
89
|
+
let nonIndexedFirst = 0;
|
|
90
|
+
return input.submeshes.flatMap((submesh) => {
|
|
91
|
+
const drawMaterial = input.materials[submesh.materialSlot] ?? input.fallbackMaterial;
|
|
92
|
+
const first = input.indexed ? submesh.indexOffset : nonIndexedFirst;
|
|
93
|
+
nonIndexedFirst += submesh.vertexCount;
|
|
94
|
+
if (drawMaterial.transparent === true) return [];
|
|
95
|
+
const draw: GpuDrivenDrawSnapshot = {
|
|
96
|
+
kind: input.indexed ? ('indexed' as const) : ('non-indexed' as const),
|
|
97
|
+
first,
|
|
98
|
+
count: input.indexed ? submesh.indexCount : submesh.vertexCount,
|
|
99
|
+
baseVertex: 0,
|
|
100
|
+
materialSlot: submesh.materialSlot,
|
|
101
|
+
topology: submesh.topology,
|
|
102
|
+
pipelineClass: `${drawMaterial.materialShaderId ?? 'forgeax::default-unlit'}|${submesh.topology}|${JSON.stringify(drawMaterial.renderState ?? null)}`,
|
|
103
|
+
materialResourceClass: gpuDrivenMaterialResourceClass(drawMaterial),
|
|
104
|
+
};
|
|
105
|
+
const prepared = input.prepare?.(draw, drawMaterial);
|
|
106
|
+
return [prepared === undefined ? draw : { ...draw, prepared }];
|
|
107
|
+
});
|
|
108
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { EntityHandle, World } from '@forgeax/engine-ecs';
|
|
2
|
-
import { createWorldProjection } from '@forgeax/engine-ecs/projection';
|
|
3
2
|
import {
|
|
4
3
|
projectHierarchy,
|
|
5
4
|
type SceneHierarchyDiagnostic,
|
|
@@ -38,14 +37,6 @@ interface ResolutionState {
|
|
|
38
37
|
readonly source: VisibilitySource;
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
interface VisibilityCacheEntry {
|
|
42
|
-
readonly changes: ReturnType<typeof createWorldProjection>;
|
|
43
|
-
readonly hierarchy: SceneHierarchySnapshot;
|
|
44
|
-
readonly snapshot: VisibilitySnapshot;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const VISIBILITY_CACHE = new WeakMap<World, VisibilityCacheEntry>();
|
|
48
|
-
|
|
49
40
|
/**
|
|
50
41
|
* Resolve author intent against the scene-owned valid parent projection.
|
|
51
42
|
* Diagnostics are preserved for callers to repair hierarchy input before retry.
|
|
@@ -54,19 +45,6 @@ export function resolveVisibility(
|
|
|
54
45
|
world: World,
|
|
55
46
|
hierarchy: SceneHierarchySnapshot = projectHierarchy(world),
|
|
56
47
|
): VisibilitySnapshot {
|
|
57
|
-
const cached = VISIBILITY_CACHE.get(world);
|
|
58
|
-
const changes = cached?.changes ?? createWorldProjection(world, { components: [Visibility] });
|
|
59
|
-
if (cached !== undefined) {
|
|
60
|
-
const evidence = changes.poll();
|
|
61
|
-
if (
|
|
62
|
-
evidence.status === 'delta' &&
|
|
63
|
-
evidence.changes.length === 0 &&
|
|
64
|
-
cached.hierarchy === hierarchy
|
|
65
|
-
) {
|
|
66
|
-
return cached.snapshot;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
48
|
// Visibility is an opt-in component. Query only the owning archetypes
|
|
71
49
|
// instead of walking every Entity row with an optional column; the latter
|
|
72
50
|
// made a World with no visibility intents pay a full-scene scan on each
|
|
@@ -158,6 +136,5 @@ export function resolveVisibility(
|
|
|
158
136
|
return resolveEntity?.(entity)?.effective ?? 'visible';
|
|
159
137
|
},
|
|
160
138
|
};
|
|
161
|
-
VISIBILITY_CACHE.set(world, { changes, hierarchy, snapshot });
|
|
162
139
|
return snapshot;
|
|
163
140
|
}
|
package/src/features/host.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EntityHandle } from '@forgeax/engine-ecs';
|
|
2
2
|
import type { RhiCaps, TextureFormat } from '@forgeax/engine-rhi';
|
|
3
3
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
4
|
+
import type { DeviceScope, LifecycleResourceSpec } from '../device/device-scope';
|
|
4
5
|
import {
|
|
5
6
|
type RenderError,
|
|
6
7
|
RenderFeatureCapabilityMissingError,
|
|
@@ -175,6 +176,7 @@ export interface RenderFeatureHost {
|
|
|
175
176
|
batches: readonly RenderFeaturePreparedResourceBatch[],
|
|
176
177
|
): Result<void, RenderError>;
|
|
177
178
|
recover(input: RenderFeatureRecoverInput): Result<void, RenderError>;
|
|
179
|
+
createRecoveryRoot(scope: DeviceScope): LifecycleResourceSpec<unknown>;
|
|
178
180
|
diagnostics(): readonly RenderFeatureDiagnostics[];
|
|
179
181
|
/** Subscribe to lifecycle projection changes; unchanged active frames are silent. */
|
|
180
182
|
subscribeDiagnostics(listener: () => void): () => void;
|
|
@@ -915,6 +917,20 @@ class FeatureHostImpl implements RenderFeatureHost {
|
|
|
915
917
|
return this.slots.map((slot) => slot.feature);
|
|
916
918
|
}
|
|
917
919
|
|
|
920
|
+
createRecoveryRoot(scope: DeviceScope): LifecycleResourceSpec<unknown> {
|
|
921
|
+
return {
|
|
922
|
+
kind: 'feature',
|
|
923
|
+
create: () => {
|
|
924
|
+
if (!scope.isAlive()) throw new Error('Feature candidate scope is not active.');
|
|
925
|
+
// The root carries the detached host owner itself. A scalar marker is
|
|
926
|
+
// not evidence that feature planning/preparation actually ran; the
|
|
927
|
+
// candidate graph and host own the prepared resources.
|
|
928
|
+
return this;
|
|
929
|
+
},
|
|
930
|
+
cleanup: () => undefined,
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
|
|
918
934
|
private publishDiagnosticsChanged(): void {
|
|
919
935
|
for (const listener of this.diagnosticsListeners) {
|
|
920
936
|
try {
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
ShaderModule,
|
|
12
12
|
} from '@forgeax/engine-rhi';
|
|
13
13
|
import { type BindGroupLayoutDescriptor, err, ok, type Result } from '@forgeax/engine-types';
|
|
14
|
+
import type { DeviceScope, LifecycleResourceSpec } from '../device/device-scope';
|
|
14
15
|
import { type RenderError, RenderFeaturePreparationFailedError } from '../errors/render';
|
|
15
16
|
import type { PipelineBuilderShaderModuleFactory } from '../pipeline-builder';
|
|
16
17
|
import type { RenderFeatureShaderModuleMode } from './types';
|
|
@@ -910,6 +911,8 @@ function createRenderFeatureGpuWorkSession(input: {
|
|
|
910
911
|
* retains the per-feature prepared GPU state and recreates it after recovery.
|
|
911
912
|
*/
|
|
912
913
|
export interface RenderFeatureGpuWorkOwner {
|
|
914
|
+
/** Candidate root carries this detached GPU-work owner itself. */
|
|
915
|
+
createRecoveryRoot(scope: DeviceScope): LifecycleResourceSpec<unknown>;
|
|
913
916
|
beginFeature(
|
|
914
917
|
featureIdentity: string,
|
|
915
918
|
generation: number,
|
|
@@ -935,9 +938,21 @@ export function createRenderFeatureGpuWorkOwner(input: {
|
|
|
935
938
|
session: RenderFeatureGpuPrepareSession;
|
|
936
939
|
}
|
|
937
940
|
>();
|
|
938
|
-
|
|
939
|
-
|
|
941
|
+
let disposed = false;
|
|
942
|
+
|
|
943
|
+
const owner: RenderFeatureGpuWorkOwner = {
|
|
944
|
+
createRecoveryRoot: (scope) => ({
|
|
945
|
+
kind: 'feature',
|
|
946
|
+
create: () => {
|
|
947
|
+
if (!scope.isAlive()) throw new Error('Feature GPU candidate scope is not active.');
|
|
948
|
+
return owner;
|
|
949
|
+
},
|
|
950
|
+
cleanup: () => undefined,
|
|
951
|
+
}),
|
|
940
952
|
beginFeature: (featureIdentity, generation, requestedShaderModuleMode = 'validated') => {
|
|
953
|
+
if (disposed) {
|
|
954
|
+
throw new Error('Render feature GPU work owner is disposed.');
|
|
955
|
+
}
|
|
941
956
|
const shaderModuleMode = requestedShaderModuleMode;
|
|
942
957
|
const existing = sessions.get(featureIdentity);
|
|
943
958
|
if (existing?.generation === generation && existing.shaderModuleMode === shaderModuleMode) {
|
|
@@ -962,6 +977,8 @@ export function createRenderFeatureGpuWorkOwner(input: {
|
|
|
962
977
|
resolveBuffer: (featureIdentity, reference) =>
|
|
963
978
|
sessions.get(featureIdentity)?.session.resolveBuffer(reference),
|
|
964
979
|
dispose: () => {
|
|
980
|
+
if (disposed) return ok(undefined);
|
|
981
|
+
disposed = true;
|
|
965
982
|
let first: RenderError | undefined;
|
|
966
983
|
for (const { session } of sessions.values()) {
|
|
967
984
|
const disposed = session.dispose();
|
|
@@ -971,4 +988,5 @@ export function createRenderFeatureGpuWorkOwner(input: {
|
|
|
971
988
|
return first === undefined ? ok(undefined) : err(first);
|
|
972
989
|
},
|
|
973
990
|
};
|
|
991
|
+
return owner;
|
|
974
992
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { TextureFormat } from '@forgeax/engine-rhi';
|
|
2
2
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
3
|
+
import type { DeviceScope, LifecycleResourceSpec } from '../device/device-scope';
|
|
3
4
|
import { type RenderError, RenderFeaturePreparationFailedError } from '../errors/render';
|
|
4
5
|
import type {
|
|
5
6
|
PreparedKind,
|
|
@@ -81,6 +82,7 @@ export interface PreparedGraphicsStore {
|
|
|
81
82
|
beginFrame(featureIdentity: string, generation: number): PreparedGraphicsTransaction;
|
|
82
83
|
snapshot(featureIdentity: string): PreparedGraphicsStoreSnapshot;
|
|
83
84
|
invalidate(featureIdentity: string, generation: number): void;
|
|
85
|
+
createRecoveryRoot(scope: DeviceScope): LifecycleResourceSpec<unknown>;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
interface Slot {
|
|
@@ -418,6 +420,21 @@ class PreparedGraphicsStoreImpl implements PreparedGraphicsStore {
|
|
|
418
420
|
}
|
|
419
421
|
}
|
|
420
422
|
|
|
423
|
+
createRecoveryRoot(scope: DeviceScope): LifecycleResourceSpec<unknown> {
|
|
424
|
+
return {
|
|
425
|
+
kind: 'buffer',
|
|
426
|
+
create: () => {
|
|
427
|
+
if (!scope.isAlive()) throw new Error('Prepared graphics candidate scope is not active.');
|
|
428
|
+
const itemCount = [...this.slots.values()].reduce(
|
|
429
|
+
(count, slot) => count + slot.items.size,
|
|
430
|
+
0,
|
|
431
|
+
);
|
|
432
|
+
return Object.freeze({ generation: scope.generation, itemCount });
|
|
433
|
+
},
|
|
434
|
+
cleanup: () => undefined,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
421
438
|
registerReference(reference: object, item: PreparedGraphicsItem): void {
|
|
422
439
|
this.references.set(reference, item);
|
|
423
440
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { PrimitiveTopology } from '@forgeax/engine-types';
|
|
2
2
|
import type { BatchTopologyInspection } from '../inspection-types';
|
|
3
|
+
import type { CameraSnapshot } from '../render-contract';
|
|
3
4
|
import type { RenderSceneApplyResult, RenderSceneSlot } from '../scene/render-scene-types';
|
|
5
|
+
import { type GpuLodRow, selectGpuLod } from '../scene/visibility/gpu-lod';
|
|
6
|
+
import { projectedHeight as measureProjectedHeight } from '../scene/visibility/lod-selector';
|
|
7
|
+
import type { PreparedGpuDrivenDraw } from './prepared-draw';
|
|
4
8
|
|
|
5
9
|
export type { BatchTopologyInspection } from '../inspection-types';
|
|
6
10
|
|
|
@@ -14,6 +18,12 @@ export interface GpuDrivenBatchKey {
|
|
|
14
18
|
readonly topology: PrimitiveTopology;
|
|
15
19
|
readonly pipelineClass: string;
|
|
16
20
|
readonly materialResourceClass: string;
|
|
21
|
+
/** Stable producer-owned identity; topology never derives this from a shader name. */
|
|
22
|
+
readonly preparedIdentity?: string;
|
|
23
|
+
/** Resource identity projected by the prepared material contract. */
|
|
24
|
+
readonly resourceIdentity?: string;
|
|
25
|
+
/** Closed admission lane for the prepared Standard PBR draw. */
|
|
26
|
+
readonly admission?: 'opaque' | 'alpha-mask';
|
|
17
27
|
}
|
|
18
28
|
|
|
19
29
|
export interface GpuDrivenCandidate {
|
|
@@ -21,6 +31,16 @@ export interface GpuDrivenCandidate {
|
|
|
21
31
|
readonly generation: number;
|
|
22
32
|
readonly drawItemIndex: number;
|
|
23
33
|
readonly instanceOrdinal: number;
|
|
34
|
+
/** Absolute coverage rows uploaded to the GPU selector; root is implicit. */
|
|
35
|
+
readonly lodCoverages?: readonly number[];
|
|
36
|
+
readonly lodHysteresis?: number;
|
|
37
|
+
readonly projectedHeight?: number;
|
|
38
|
+
readonly lodRanges?: readonly {
|
|
39
|
+
readonly first: number;
|
|
40
|
+
readonly count: number;
|
|
41
|
+
readonly baseVertex: number;
|
|
42
|
+
}[];
|
|
43
|
+
readonly prepared?: PreparedGpuDrivenDraw;
|
|
24
44
|
}
|
|
25
45
|
|
|
26
46
|
export interface GpuDrivenBatch {
|
|
@@ -40,6 +60,32 @@ export interface SubmissionPlan {
|
|
|
40
60
|
readonly visibleCapacity: number;
|
|
41
61
|
}
|
|
42
62
|
|
|
63
|
+
export interface GpuLodCandidateInput {
|
|
64
|
+
readonly candidate: GpuDrivenCandidate;
|
|
65
|
+
readonly rows: readonly GpuLodRow[];
|
|
66
|
+
readonly projectedHeight: number;
|
|
67
|
+
readonly previousLevel: number;
|
|
68
|
+
readonly historyValid: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface GpuLodCompactCandidate {
|
|
72
|
+
readonly candidate: GpuDrivenCandidate;
|
|
73
|
+
readonly level: number;
|
|
74
|
+
readonly confidence: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Selects one level per stable topology candidate without mutating membership. */
|
|
78
|
+
export function compactGpuLodCandidates(
|
|
79
|
+
inputs: readonly GpuLodCandidateInput[],
|
|
80
|
+
): readonly GpuLodCompactCandidate[] {
|
|
81
|
+
return Object.freeze(
|
|
82
|
+
inputs.map((input) => {
|
|
83
|
+
const selection = selectGpuLod(input.rows, input);
|
|
84
|
+
return Object.freeze({ candidate: input.candidate, ...selection });
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
43
89
|
interface MutableBatch {
|
|
44
90
|
readonly batchId: number;
|
|
45
91
|
readonly generation: number;
|
|
@@ -56,27 +102,97 @@ function eligibleKeys(slot: RenderSceneSlot): readonly GpuDrivenBatchKey[] {
|
|
|
56
102
|
snapshot.instances?.instanceCount === 0 ||
|
|
57
103
|
snapshot.localAabb === undefined ||
|
|
58
104
|
snapshot.skin !== undefined ||
|
|
105
|
+
snapshot.morph !== undefined ||
|
|
59
106
|
snapshot.spriteInstances !== undefined
|
|
60
107
|
) {
|
|
61
108
|
return [];
|
|
62
109
|
}
|
|
63
|
-
return draws.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
110
|
+
return draws.flatMap((draw) => {
|
|
111
|
+
const prepared = draw.prepared;
|
|
112
|
+
const material = snapshot.materials[draw.materialSlot] ?? snapshot.material;
|
|
113
|
+
if (prepared !== undefined) {
|
|
114
|
+
const isStandardPbr =
|
|
115
|
+
(material.materialShaderId === 'forgeax::default-standard-pbr' &&
|
|
116
|
+
prepared.identity.material === 'forgeax::default-standard-pbr') ||
|
|
117
|
+
(material.materialShaderId === 'forgeax::default-standard-pbr-skin' &&
|
|
118
|
+
prepared.identity.material === 'forgeax::default-standard-pbr-skin');
|
|
119
|
+
const isAlphaBlend =
|
|
120
|
+
material.transparent === true || material.renderState?.blend !== undefined;
|
|
121
|
+
if (!isStandardPbr || isAlphaBlend || prepared.identity.deformation !== 'rigid') return [];
|
|
122
|
+
const preparedIdentity = `${prepared.identity.material}|${prepared.identity.geometry}|${prepared.identity.deformation}`;
|
|
123
|
+
const admission =
|
|
124
|
+
typeof material.paramSnapshot?.alphaCutoff === 'number' ? 'alpha-mask' : 'opaque';
|
|
125
|
+
return [
|
|
126
|
+
{
|
|
127
|
+
assetHandle: snapshot.assetHandle,
|
|
128
|
+
drawKind: draw.kind,
|
|
129
|
+
first: prepared.first,
|
|
130
|
+
count: prepared.count,
|
|
131
|
+
baseVertex: prepared.baseVertex,
|
|
132
|
+
materialSlot: draw.materialSlot,
|
|
133
|
+
topology: prepared.topology,
|
|
134
|
+
pipelineClass: preparedIdentity,
|
|
135
|
+
materialResourceClass: draw.materialResourceClass,
|
|
136
|
+
preparedIdentity,
|
|
137
|
+
resourceIdentity: draw.materialResourceClass,
|
|
138
|
+
admission,
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
}
|
|
142
|
+
return [
|
|
143
|
+
{
|
|
144
|
+
assetHandle: snapshot.assetHandle,
|
|
145
|
+
drawKind: draw.kind,
|
|
146
|
+
first: draw.first,
|
|
147
|
+
count: draw.count,
|
|
148
|
+
baseVertex: draw.baseVertex,
|
|
149
|
+
materialSlot: draw.materialSlot,
|
|
150
|
+
topology: draw.topology,
|
|
151
|
+
pipelineClass: draw.pipelineClass,
|
|
152
|
+
materialResourceClass: draw.materialResourceClass,
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
});
|
|
74
156
|
}
|
|
75
157
|
|
|
76
158
|
function keyText(key: GpuDrivenBatchKey): string {
|
|
77
159
|
return JSON.stringify(key);
|
|
78
160
|
}
|
|
79
161
|
|
|
162
|
+
/**
|
|
163
|
+
* A GPU indirect draw has one index/vertex range for the whole batch. LOD
|
|
164
|
+
* selection is per candidate, so sharing a batch between LOD candidates would
|
|
165
|
+
* let `finalizeView` pick the first candidate's range for every visible
|
|
166
|
+
* instance. Keep LOD candidates in single-candidate batches; ordinary meshes
|
|
167
|
+
* retain the existing compatibility batching path.
|
|
168
|
+
*/
|
|
169
|
+
function candidateBatchText(
|
|
170
|
+
key: GpuDrivenBatchKey,
|
|
171
|
+
primitiveIndex: number,
|
|
172
|
+
drawItemIndex: number,
|
|
173
|
+
instanceOrdinal: number,
|
|
174
|
+
hasLod: boolean,
|
|
175
|
+
): string {
|
|
176
|
+
return hasLod
|
|
177
|
+
? `${keyText(key)}|lod:${primitiveIndex}:${drawItemIndex}:${instanceOrdinal}`
|
|
178
|
+
: keyText(key);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function membershipTexts(slot: RenderSceneSlot): readonly string[] {
|
|
182
|
+
const keys = eligibleKeys(slot);
|
|
183
|
+
const instanceCount = slot.snapshot.instances?.instanceCount ?? 1;
|
|
184
|
+
const hasLod = (slot.snapshot.lods?.length ?? 0) > 0;
|
|
185
|
+
const texts: string[] = [];
|
|
186
|
+
for (let drawItemIndex = 0; drawItemIndex < keys.length; drawItemIndex += 1) {
|
|
187
|
+
const key = keys[drawItemIndex];
|
|
188
|
+
if (key === undefined) continue;
|
|
189
|
+
for (let instanceOrdinal = 0; instanceOrdinal < instanceCount; instanceOrdinal += 1) {
|
|
190
|
+
texts.push(candidateBatchText(key, slot.slot, drawItemIndex, instanceOrdinal, hasLod));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return texts;
|
|
194
|
+
}
|
|
195
|
+
|
|
80
196
|
function alignInstanceBase(value: number): number {
|
|
81
197
|
// Raster binds each batch's visible-index and compact-transform segment at
|
|
82
198
|
// a static storage-buffer offset. WebGPU requires those offsets to satisfy
|
|
@@ -86,6 +202,42 @@ function alignInstanceBase(value: number): number {
|
|
|
86
202
|
return Math.ceil(value / 64) * 64;
|
|
87
203
|
}
|
|
88
204
|
|
|
205
|
+
export function projectedHeightForCandidate(slot: RenderSceneSlot, camera: CameraSnapshot): number {
|
|
206
|
+
const aabb = slot.snapshot.localAabb;
|
|
207
|
+
if (aabb === undefined || aabb.length < 6) return Number.NaN;
|
|
208
|
+
const halfX = Math.abs((aabb[3] ?? 0) - (aabb[0] ?? 0)) * 0.5;
|
|
209
|
+
const halfY = Math.abs((aabb[4] ?? 0) - (aabb[1] ?? 0)) * 0.5;
|
|
210
|
+
const halfZ = Math.abs((aabb[5] ?? 0) - (aabb[2] ?? 0)) * 0.5;
|
|
211
|
+
const world = slot.snapshot.transform.world;
|
|
212
|
+
// Transform the local AABB's half extents through the absolute value of the
|
|
213
|
+
// world 3x3. This is the conservative world-space sphere bound for every
|
|
214
|
+
// rotation and signed/non-uniform scale, and keeps CPU projection aligned
|
|
215
|
+
// with the world transform uploaded to the GPU selector.
|
|
216
|
+
const worldHalfX =
|
|
217
|
+
Math.abs(world[0] ?? 0) * halfX +
|
|
218
|
+
Math.abs(world[4] ?? 0) * halfY +
|
|
219
|
+
Math.abs(world[8] ?? 0) * halfZ;
|
|
220
|
+
const worldHalfY =
|
|
221
|
+
Math.abs(world[1] ?? 0) * halfX +
|
|
222
|
+
Math.abs(world[5] ?? 0) * halfY +
|
|
223
|
+
Math.abs(world[9] ?? 0) * halfZ;
|
|
224
|
+
const worldHalfZ =
|
|
225
|
+
Math.abs(world[2] ?? 0) * halfX +
|
|
226
|
+
Math.abs(world[6] ?? 0) * halfY +
|
|
227
|
+
Math.abs(world[10] ?? 0) * halfZ;
|
|
228
|
+
const radius = Math.hypot(worldHalfX, worldHalfY, worldHalfZ);
|
|
229
|
+
const dx = (world[12] ?? 0) - (camera.position[0] ?? 0);
|
|
230
|
+
const dy = (world[13] ?? 0) - (camera.position[1] ?? 0);
|
|
231
|
+
const dz = (world[14] ?? 0) - (camera.position[2] ?? 0);
|
|
232
|
+
return measureProjectedHeight({
|
|
233
|
+
radius,
|
|
234
|
+
depth: Math.hypot(dx, dy, dz),
|
|
235
|
+
projection: camera.projection,
|
|
236
|
+
fov: camera.fov,
|
|
237
|
+
orthoHeight: Math.abs(camera.orthoTop - camera.orthoBottom),
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
89
241
|
/** Stable compatibility grouping; per-view visibility never mutates this owner. */
|
|
90
242
|
export class BatchTopology {
|
|
91
243
|
private readonly batches = new Map<string, MutableBatch>();
|
|
@@ -120,15 +272,17 @@ export class BatchTopology {
|
|
|
120
272
|
changed = this.remove(slot.slot) || changed;
|
|
121
273
|
changed = this.add(slot) || changed;
|
|
122
274
|
}
|
|
275
|
+
// Most updated slots are transform-only. A full renderable update can
|
|
276
|
+
// still carry a changed material/geometry/draw topology, so compare the
|
|
277
|
+
// stable batch memberships and patch only when that key actually changed.
|
|
278
|
+
// This keeps moving entities on the zero-work transform lane while making
|
|
279
|
+
// same-entity resource edits visible to the GPU-driven owner.
|
|
123
280
|
for (const slot of delta.updatedSlots) {
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
Array.from({ length: instanceCount }, () => keyText(key)),
|
|
127
|
-
);
|
|
128
|
-
const current = this.membershipByPrimitive.get(slot.slot) ?? [];
|
|
281
|
+
const previous = this.membershipByPrimitive.get(slot.slot) ?? [];
|
|
282
|
+
const next = membershipTexts(slot);
|
|
129
283
|
if (
|
|
130
|
-
|
|
131
|
-
|
|
284
|
+
previous.length === next.length &&
|
|
285
|
+
previous.every((membership, index) => membership.batchText === next[index])
|
|
132
286
|
) {
|
|
133
287
|
continue;
|
|
134
288
|
}
|
|
@@ -199,26 +353,50 @@ export class BatchTopology {
|
|
|
199
353
|
this.ineligiblePrimitives.delete(slot.slot);
|
|
200
354
|
const memberships: Array<{ batchText: string; candidateKey: string }> = [];
|
|
201
355
|
const instanceCount = slot.snapshot.instances?.instanceCount ?? 1;
|
|
356
|
+
const hasLod = (slot.snapshot.lods?.length ?? 0) > 0;
|
|
202
357
|
for (let drawItemIndex = 0; drawItemIndex < keys.length; drawItemIndex += 1) {
|
|
203
358
|
const key = keys[drawItemIndex];
|
|
204
359
|
if (key === undefined) continue;
|
|
205
|
-
const text = keyText(key);
|
|
206
|
-
let batch = this.batches.get(text);
|
|
207
|
-
if (batch === undefined) {
|
|
208
|
-
const reused = this.freeBatchIds.pop();
|
|
209
|
-
const batchId = reused ?? this.generationByBatchId.length;
|
|
210
|
-
const generation = reused === undefined ? 0 : (this.generationByBatchId[batchId] ?? -1) + 1;
|
|
211
|
-
this.generationByBatchId[batchId] = generation;
|
|
212
|
-
batch = { batchId, generation, key, candidates: new Map() };
|
|
213
|
-
this.batches.set(text, batch);
|
|
214
|
-
}
|
|
215
360
|
for (let instanceOrdinal = 0; instanceOrdinal < instanceCount; instanceOrdinal += 1) {
|
|
361
|
+
const text = candidateBatchText(key, slot.slot, drawItemIndex, instanceOrdinal, hasLod);
|
|
362
|
+
let batch = this.batches.get(text);
|
|
363
|
+
if (batch === undefined) {
|
|
364
|
+
const reused = this.freeBatchIds.pop();
|
|
365
|
+
const batchId = reused ?? this.generationByBatchId.length;
|
|
366
|
+
const generation =
|
|
367
|
+
reused === undefined ? 0 : (this.generationByBatchId[batchId] ?? -1) + 1;
|
|
368
|
+
this.generationByBatchId[batchId] = generation;
|
|
369
|
+
batch = { batchId, generation, key, candidates: new Map() };
|
|
370
|
+
this.batches.set(text, batch);
|
|
371
|
+
}
|
|
216
372
|
const candidateKey = `${slot.slot}:${drawItemIndex}:${instanceOrdinal}`;
|
|
373
|
+
const draw = slot.snapshot.gpuDrivenDraws?.[drawItemIndex];
|
|
374
|
+
const prepared = draw?.prepared;
|
|
217
375
|
batch.candidates.set(candidateKey, {
|
|
218
376
|
primitiveIndex: slot.slot,
|
|
219
377
|
generation: slot.generation,
|
|
220
378
|
drawItemIndex,
|
|
221
379
|
instanceOrdinal,
|
|
380
|
+
...(draw?.projectedHeight === undefined ? {} : { projectedHeight: draw.projectedHeight }),
|
|
381
|
+
...(slot.snapshot.lods === undefined
|
|
382
|
+
? {}
|
|
383
|
+
: {
|
|
384
|
+
lodCoverages: [1, ...slot.snapshot.lods.map((lod) => lod.screenCoverage)],
|
|
385
|
+
...(slot.snapshot.gpuDrivenDraws?.[drawItemIndex]?.lodRanges === undefined
|
|
386
|
+
? {}
|
|
387
|
+
: {
|
|
388
|
+
lodRanges: slot.snapshot.gpuDrivenDraws[drawItemIndex]
|
|
389
|
+
?.lodRanges as readonly {
|
|
390
|
+
readonly first: number;
|
|
391
|
+
readonly count: number;
|
|
392
|
+
readonly baseVertex: number;
|
|
393
|
+
}[],
|
|
394
|
+
}),
|
|
395
|
+
...(slot.snapshot.lodHysteresis === undefined
|
|
396
|
+
? {}
|
|
397
|
+
: { lodHysteresis: slot.snapshot.lodHysteresis }),
|
|
398
|
+
}),
|
|
399
|
+
...(prepared === undefined ? {} : { prepared }),
|
|
222
400
|
});
|
|
223
401
|
memberships.push({ batchText: text, candidateKey });
|
|
224
402
|
}
|