@forgeax/engine-render 0.1.21 → 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 +150 -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.map +1 -1
- package/dist/assembly/factory.d.ts +14 -6
- 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/authoring.mjs +1 -1
- 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-FS2KNUQH.mjs → chunk-FF7K3FSO.mjs} +253 -489
- 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-6OPXDQ2E.mjs → chunk-QODA5UKU.mjs} +33 -294
- 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-5YADUCA7.mjs → chunk-ZUWKAZ2I.mjs} +585 -991
- 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/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 +10437 -10044
- 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/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 +26 -1
- package/dist/errors/render.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/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 +98 -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 +3 -3
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/index.d.ts +12 -1
- 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 +58 -149
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +26 -12
- 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/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 +50 -10
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +7 -3
- 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 +6 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +3 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +57 -6
- 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/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 +14 -8
- 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.d.ts +104 -16
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +12 -1
- 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 +103 -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/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 +13 -1
- package/src/__tests__/direct-light-snapshot.unit.test.ts +59 -3
- 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 +33 -0
- 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__/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__/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__/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__/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 +76 -0
- 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-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 +69 -0
- 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/assembly/backend-contract.ts +13 -0
- package/src/assembly/device-feature-admission.ts +16 -9
- package/src/assembly/factory.ts +547 -93
- package/src/assembly/host-contract.ts +10 -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/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/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/lifecycle.ts +8 -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 +55 -1
- package/src/extract/camera.ts +3 -3
- package/src/extract/gpu-driven.ts +108 -0
- package/src/extract/visibility.ts +0 -23
- 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 +953 -41
- package/src/gpu-driven/view-gpu.ts +411 -29
- package/src/gpu-scene-schema.ts +13 -0
- package/src/gpu-scene.ts +134 -65
- package/src/gpu-usage.ts +0 -1
- package/src/hdrp-buffers.ts +6 -6
- package/src/index.ts +74 -0
- package/src/inspection-types.ts +220 -1
- package/src/internal.ts +38 -0
- package/src/light-buffer-layout.ts +154 -324
- package/src/materials.ts +16 -2
- package/src/pbr-pipeline.ts +151 -45
- 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/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 +23 -1
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
- package/src/record/frame-lighting.ts +252 -53
- package/src/record/frame-snapshot.ts +57 -12
- package/src/record/frame.ts +410 -93
- package/src/record/gpu-timing.ts +108 -44
- package/src/record/helpers.ts +0 -58
- package/src/record/main-pass-geometry.ts +204 -39
- package/src/record/main-pass-material.ts +8 -1
- package/src/record/main-pass-sprite-draws.ts +52 -85
- package/src/record/mesh-ssbo.ts +47 -36
- package/src/record/render-context.ts +65 -4
- package/src/record/shadow-pass.ts +66 -40
- package/src/record/typed-frame-graph.ts +225 -83
- package/src/record/view-ubo.ts +14 -24
- 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 +17 -5
- package/src/render-pipeline.ts +5 -0
- package/src/render-system-extract.ts +493 -134
- package/src/render-system.ts +811 -615
- 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 +848 -183
- 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 +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/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.map +0 -1
|
@@ -22,6 +22,7 @@ import type { InstanceBufferCacheEntry } from '../instance-buffer-cache';
|
|
|
22
22
|
import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from '../materials';
|
|
23
23
|
import {
|
|
24
24
|
createPbrSkinMeshBindGroupEntries,
|
|
25
|
+
isStandardPbrMaterialShader,
|
|
25
26
|
pbrSkinMeshDynamicOffsets,
|
|
26
27
|
SKIN_MATERIAL_SHADER_ID,
|
|
27
28
|
} from '../pbr-pipeline';
|
|
@@ -35,6 +36,11 @@ import type { PointsLinesRecordPlan } from '../points-lines/record';
|
|
|
35
36
|
import { POINTS_LINES_MATERIAL_SHADER_ID } from '../points-lines/record';
|
|
36
37
|
import type { RenderRecordPhase } from '../render-contract';
|
|
37
38
|
import type { MaterialSnapshot } from '../render-system-extract';
|
|
39
|
+
import {
|
|
40
|
+
PROBE_BLEND_RECORD_BYTE_SIZE,
|
|
41
|
+
PROBE_BLEND_RECORD_STRIDE,
|
|
42
|
+
probeBlendRecordOffset,
|
|
43
|
+
} from '../scene/probe-blend-record';
|
|
38
44
|
import { worldEntityKey } from './frame-snapshot';
|
|
39
45
|
import {
|
|
40
46
|
geometryRenderStateForTopology,
|
|
@@ -58,12 +64,15 @@ import { POINTS_LINES_VIEW_SLOT_STRIDE, writePointsLinesViewUbo } from './view-u
|
|
|
58
64
|
type GeometryInstanceDraw = {
|
|
59
65
|
readonly instanceBuffer: Buffer;
|
|
60
66
|
readonly instanceBindGroup: BindGroup;
|
|
67
|
+
/** -1 means the no-probe layout and therefore no dynamic offset. */
|
|
68
|
+
readonly probeOffset: number;
|
|
61
69
|
readonly instanceCount: number;
|
|
62
70
|
};
|
|
63
71
|
|
|
64
72
|
type GeometryBindingState = {
|
|
65
73
|
pipeline: RenderPipeline | null;
|
|
66
74
|
instancesBuffer: Buffer | null;
|
|
75
|
+
probeOffset: number;
|
|
67
76
|
};
|
|
68
77
|
|
|
69
78
|
type MaterialPipelineLookup = {
|
|
@@ -77,6 +86,7 @@ type MaterialPipelineLookup = {
|
|
|
77
86
|
readonly layoutProjection: import('@forgeax/engine-geometry').VertexLayoutProjection;
|
|
78
87
|
readonly sampleCount: number;
|
|
79
88
|
readonly colorFormatOverride: GPUTextureFormat | undefined;
|
|
89
|
+
readonly additionalColorFormats: readonly GPUTextureFormat[] | undefined;
|
|
80
90
|
readonly handle: MaterialShaderPipelineEntry | null;
|
|
81
91
|
};
|
|
82
92
|
|
|
@@ -138,9 +148,17 @@ function submitSubmeshDraws(
|
|
|
138
148
|
state.pipeline = pipeline;
|
|
139
149
|
}
|
|
140
150
|
for (const instanceDraw of instanceDraws) {
|
|
141
|
-
if (
|
|
142
|
-
|
|
151
|
+
if (
|
|
152
|
+
instanceDraw.instanceBuffer !== state.instancesBuffer ||
|
|
153
|
+
instanceDraw.probeOffset !== state.probeOffset
|
|
154
|
+
) {
|
|
155
|
+
if (instanceDraw.probeOffset < 0) {
|
|
156
|
+
pass.setBindGroup(3, instanceDraw.instanceBindGroup);
|
|
157
|
+
} else {
|
|
158
|
+
pass.setBindGroup(3, instanceDraw.instanceBindGroup, [instanceDraw.probeOffset]);
|
|
159
|
+
}
|
|
143
160
|
state.instancesBuffer = instanceDraw.instanceBuffer;
|
|
161
|
+
state.probeOffset = instanceDraw.probeOffset;
|
|
144
162
|
}
|
|
145
163
|
if (indexed) {
|
|
146
164
|
pass.drawIndexed(indexCount, instanceDraw.instanceCount, indexOffset, 0, 0);
|
|
@@ -226,12 +244,14 @@ export function recordGeometryDraws(
|
|
|
226
244
|
const bindingState: GeometryBindingState = {
|
|
227
245
|
pipeline: null,
|
|
228
246
|
instancesBuffer: null,
|
|
247
|
+
probeOffset: -1,
|
|
229
248
|
};
|
|
230
249
|
const identityInstanceBuffer = pipelineState.identityInstanceBuffer;
|
|
231
250
|
const identityInstanceDraws: readonly GeometryInstanceDraw[] = [
|
|
232
251
|
{
|
|
233
252
|
instanceBuffer: identityInstanceBuffer,
|
|
234
|
-
instanceBindGroup: resolveGeometryInstancesBindGroup(c, identityInstanceBuffer),
|
|
253
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(c, identityInstanceBuffer, undefined),
|
|
254
|
+
probeOffset: -1,
|
|
235
255
|
instanceCount: 1,
|
|
236
256
|
},
|
|
237
257
|
];
|
|
@@ -253,6 +273,9 @@ export function recordGeometryDraws(
|
|
|
253
273
|
// renderer's authoritative cache still owns lifetime/invalidation, while
|
|
254
274
|
// this frame-local table removes the hot call/lookup overhead.
|
|
255
275
|
const materialPipelineLookupCache = new Map<string, Map<string, MaterialPipelineLookup[]>>();
|
|
276
|
+
const recordOcclusionCandidate = (draw: () => void): void => {
|
|
277
|
+
draw();
|
|
278
|
+
};
|
|
256
279
|
const resolveMaterialPipeline = (
|
|
257
280
|
materialShaderId: string,
|
|
258
281
|
renderState: MaterialSnapshot['renderState'],
|
|
@@ -262,6 +285,19 @@ export function recordGeometryDraws(
|
|
|
262
285
|
colorFormat: GPUTextureFormat | undefined,
|
|
263
286
|
layoutProjection: import('@forgeax/engine-geometry').VertexLayoutProjection,
|
|
264
287
|
): MaterialShaderPipelineEntry | null => {
|
|
288
|
+
// The fallback MRT is an extension of the built-in Standard PBR output
|
|
289
|
+
// contract only. The render pass may carry a second attachment whenever
|
|
290
|
+
// another renderable needs S_fallback, but shaders such as unlit, sprite,
|
|
291
|
+
// and the skin PBR variant still expose only @location(0). Passing that
|
|
292
|
+
// attachment into their PSO would make WebGPU reject the pipeline before
|
|
293
|
+
// the first draw ("Color target has no corresponding fragment stage
|
|
294
|
+
// output"). Keep the graph attachment shared while deriving pipeline
|
|
295
|
+
// targets from the shader's actual output contract.
|
|
296
|
+
const reflectionFallbackFormats =
|
|
297
|
+
materialShaderId === 'forgeax::default-standard-pbr' &&
|
|
298
|
+
c.reflectionFallbackColorFormat !== undefined
|
|
299
|
+
? [c.reflectionFallbackColorFormat]
|
|
300
|
+
: undefined;
|
|
265
301
|
const renderStateKey = renderStateHash(renderState);
|
|
266
302
|
const shaderLookupCache = materialPipelineLookupCache.get(materialShaderId);
|
|
267
303
|
const cachedLookups = shaderLookupCache?.get(renderStateKey);
|
|
@@ -276,7 +312,8 @@ export function recordGeometryDraws(
|
|
|
276
312
|
cached.passKind === passKind &&
|
|
277
313
|
cached.layoutProjection.digest === layoutProjection.digest &&
|
|
278
314
|
cached.sampleCount === sampleCount &&
|
|
279
|
-
cached.colorFormatOverride === colorFormat
|
|
315
|
+
cached.colorFormatOverride === colorFormat &&
|
|
316
|
+
cached.additionalColorFormats?.join(',') === reflectionFallbackFormats?.join(',')
|
|
280
317
|
) {
|
|
281
318
|
return cached.handle;
|
|
282
319
|
}
|
|
@@ -292,6 +329,12 @@ export function recordGeometryDraws(
|
|
|
292
329
|
return null;
|
|
293
330
|
}
|
|
294
331
|
const resolvedVariantSet = resolvedVariantSetResult.value;
|
|
332
|
+
const fallbackVariantSet =
|
|
333
|
+
materialShaderId !== 'forgeax::default-standard-pbr'
|
|
334
|
+
? resolvedVariantSet
|
|
335
|
+
: c.reflectionFallbackColorFormat !== undefined && resolvedVariantSet === ''
|
|
336
|
+
? ''
|
|
337
|
+
: `${resolvedVariantSet === undefined || resolvedVariantSet === '' ? '' : `${resolvedVariantSet}+`}REFLECTION_FALLBACK_AVAILABLE=${c.reflectionFallbackColorFormat !== undefined}`;
|
|
295
338
|
const resolvePipeline = () =>
|
|
296
339
|
runtime.getMaterialShaderPipelineEntry?.(
|
|
297
340
|
materialShaderId,
|
|
@@ -299,7 +342,7 @@ export function recordGeometryDraws(
|
|
|
299
342
|
renderState,
|
|
300
343
|
topology,
|
|
301
344
|
indexFormat,
|
|
302
|
-
|
|
345
|
+
fallbackVariantSet,
|
|
303
346
|
passKind,
|
|
304
347
|
undefined,
|
|
305
348
|
sampleCount,
|
|
@@ -308,6 +351,9 @@ export function recordGeometryDraws(
|
|
|
308
351
|
undefined,
|
|
309
352
|
undefined,
|
|
310
353
|
layoutProjection,
|
|
354
|
+
undefined,
|
|
355
|
+
undefined,
|
|
356
|
+
reflectionFallbackFormats,
|
|
311
357
|
) ?? null;
|
|
312
358
|
const handle =
|
|
313
359
|
profilePhase === undefined
|
|
@@ -332,6 +378,7 @@ export function recordGeometryDraws(
|
|
|
332
378
|
layoutProjection,
|
|
333
379
|
sampleCount,
|
|
334
380
|
colorFormatOverride: colorFormat,
|
|
381
|
+
additionalColorFormats: reflectionFallbackFormats,
|
|
335
382
|
handle,
|
|
336
383
|
};
|
|
337
384
|
if (shaderLookupCache === undefined) {
|
|
@@ -361,7 +408,12 @@ export function recordGeometryDraws(
|
|
|
361
408
|
|
|
362
409
|
if (
|
|
363
410
|
passKind === 'forward' &&
|
|
364
|
-
c.gpuDrivenEntityKeys.has(
|
|
411
|
+
c.gpuDrivenEntityKeys.has(
|
|
412
|
+
worldEntityKey(
|
|
413
|
+
c.gpuDrivenWorldKeys?.[entry.source.worldId] ?? entry.source.worldId,
|
|
414
|
+
entry.source.entityKey,
|
|
415
|
+
),
|
|
416
|
+
)
|
|
365
417
|
) {
|
|
366
418
|
continue;
|
|
367
419
|
}
|
|
@@ -454,12 +506,11 @@ export function recordGeometryDraws(
|
|
|
454
506
|
const pointsLinesMeshGroup = meshBindGroup ?? meshGroup2;
|
|
455
507
|
if (pointsLinesMeshGroup === null) continue;
|
|
456
508
|
pass.setBindGroup(2, pointsLinesMeshGroup, meshGroup2DynamicOffsets);
|
|
457
|
-
|
|
458
|
-
3,
|
|
509
|
+
const pointsLinesInstancesBg =
|
|
459
510
|
identityInstanceDraws[0]?.instanceBindGroup ??
|
|
460
|
-
|
|
461
|
-
);
|
|
462
|
-
recordPointsLinesDraw(pass, pointsLinesSubmission.plan);
|
|
511
|
+
resolveGeometryInstancesBindGroup(c, identityInstanceBuffer, undefined);
|
|
512
|
+
pass.setBindGroup(3, pointsLinesInstancesBg);
|
|
513
|
+
recordOcclusionCandidate(() => recordPointsLinesDraw(pass, pointsLinesSubmission.plan));
|
|
463
514
|
pass.setBindGroup(0, viewBindGroup as BindGroup, [viewBindGroupDynamicOffset, 0]);
|
|
464
515
|
continue;
|
|
465
516
|
}
|
|
@@ -487,7 +538,7 @@ export function recordGeometryDraws(
|
|
|
487
538
|
// length instead.
|
|
488
539
|
if (pipelineTag === 'unlit') dispatchCounts.unlit += 1;
|
|
489
540
|
|
|
490
|
-
const instanceDraws = resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws);
|
|
541
|
+
const instanceDraws = resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, false);
|
|
491
542
|
if (instanceDraws === null) continue;
|
|
492
543
|
|
|
493
544
|
// feat-20260611 R2 / M8 / w28 (IS-14): skin entries need a 3-binding
|
|
@@ -518,6 +569,8 @@ export function recordGeometryDraws(
|
|
|
518
569
|
meshGroup2DynamicOffsets[0] = i * MESH_PER_ENTITY_STRIDE;
|
|
519
570
|
let group2DynamicOffsets: readonly number[] = meshGroup2DynamicOffsets;
|
|
520
571
|
const isSkinEntry = entry.source.skin !== undefined;
|
|
572
|
+
const probeBlendRecordAvailable =
|
|
573
|
+
runtime.device.caps.storageBuffer && entry.source.probeBlendRecord !== undefined;
|
|
521
574
|
// feat-20260612-skin-palette-per-frame-upload M1 / m1-3 + M6: the
|
|
522
575
|
// record stage reads the GPU buffer reference through
|
|
523
576
|
// `entry.source.skin.buffer` (per-slice carrier set at extract time
|
|
@@ -567,6 +620,7 @@ export function recordGeometryDraws(
|
|
|
567
620
|
c.standardLighting,
|
|
568
621
|
runtime.device.caps.storageBuffer,
|
|
569
622
|
entry.mesh.layoutProjection.attributes.some((attribute) => attribute.key === 'color'),
|
|
623
|
+
probeBlendRecordAvailable,
|
|
570
624
|
),
|
|
571
625
|
);
|
|
572
626
|
if (!skinVariantSetResult.ok) runtime.errorRegistry.fire(skinVariantSetResult.error);
|
|
@@ -588,6 +642,9 @@ export function recordGeometryDraws(
|
|
|
588
642
|
undefined,
|
|
589
643
|
undefined,
|
|
590
644
|
entry.mesh.layoutProjection,
|
|
645
|
+
undefined,
|
|
646
|
+
undefined,
|
|
647
|
+
undefined,
|
|
591
648
|
) ?? null)
|
|
592
649
|
: null;
|
|
593
650
|
if (skinResources !== null && skinPsoProbe !== null) {
|
|
@@ -794,6 +851,8 @@ export function recordGeometryDraws(
|
|
|
794
851
|
entry.source.skin !== undefined
|
|
795
852
|
? SKIN_MATERIAL_SHADER_ID
|
|
796
853
|
: submeshMaterial.materialShaderId;
|
|
854
|
+
const probeBlendAvailable =
|
|
855
|
+
probeBlendRecordAvailable && isStandardPbrMaterialShader(smMaterialShaderId);
|
|
797
856
|
const isSpriteShader =
|
|
798
857
|
smMaterialShaderId === 'forgeax::sprite' || smMaterialShaderId === 'forgeax::sprite-lit';
|
|
799
858
|
// Preserve the dedicated sprite-pass state when the linear-LDR graph
|
|
@@ -869,6 +928,7 @@ export function recordGeometryDraws(
|
|
|
869
928
|
c.standardLighting,
|
|
870
929
|
runtime.device.caps.storageBuffer,
|
|
871
930
|
hasVertexColor,
|
|
931
|
+
probeBlendAvailable,
|
|
872
932
|
);
|
|
873
933
|
// Sprite's base request must retain the boot-selected artifact. Only
|
|
874
934
|
// SpriteInstances uses the explicit empty key for the
|
|
@@ -884,19 +944,12 @@ export function recordGeometryDraws(
|
|
|
884
944
|
: capabilityVariantSet === ''
|
|
885
945
|
? entry.variantSet
|
|
886
946
|
: `${capabilityVariantSet}+${entry.variantSet}`;
|
|
887
|
-
const projectionVariantSetResult = isSpriteShader
|
|
888
|
-
? ({ ok: true, value: variantSet } as const)
|
|
889
|
-
: variantSetFromVertexLayoutProjection(entry.mesh.layoutProjection, variantSet);
|
|
890
|
-
if (!projectionVariantSetResult.ok) {
|
|
891
|
-
runtime.errorRegistry.fire(projectionVariantSetResult.error);
|
|
892
|
-
continue;
|
|
893
|
-
}
|
|
894
947
|
const cachedPipeline = resolveMaterialPipeline(
|
|
895
948
|
smMaterialShaderId,
|
|
896
949
|
pipelineRenderState,
|
|
897
950
|
smTopology,
|
|
898
951
|
entry.mesh.indexFormat,
|
|
899
|
-
|
|
952
|
+
variantSet,
|
|
900
953
|
colorFormatOverride,
|
|
901
954
|
entry.mesh.layoutProjection,
|
|
902
955
|
);
|
|
@@ -922,6 +975,18 @@ export function recordGeometryDraws(
|
|
|
922
975
|
if (smPipelineHandle === null) {
|
|
923
976
|
continue;
|
|
924
977
|
}
|
|
978
|
+
// The probe record is an ABI extension of the built-in Standard PBR
|
|
979
|
+
// shaders only. RenderScene may retain a record on every projected
|
|
980
|
+
// renderable, but unlit/custom shaders still use the one-binding
|
|
981
|
+
// instances BGL and must never receive the probe bind group. Resolve
|
|
982
|
+
// this per submesh so mixed-material meshes cannot cross the layouts.
|
|
983
|
+
const instanceDraws = resolveGeometryInstanceBuffer(
|
|
984
|
+
c,
|
|
985
|
+
entry,
|
|
986
|
+
identityInstanceDraws,
|
|
987
|
+
probeBlendAvailable,
|
|
988
|
+
);
|
|
989
|
+
if (instanceDraws === null) continue;
|
|
925
990
|
// Standard clustered PBR variants declare the unified cluster/SSAO
|
|
926
991
|
// group(2) layout. Unlit and other URP-layout materials must bind the
|
|
927
992
|
// ordinary mesh group instead; choosing one group for the whole pass
|
|
@@ -941,18 +1006,7 @@ export function recordGeometryDraws(
|
|
|
941
1006
|
pass.setBindGroup(2, group2BindGroup, group2DynamicOffsets);
|
|
942
1007
|
|
|
943
1008
|
if (profilePhase === undefined) {
|
|
944
|
-
|
|
945
|
-
pass,
|
|
946
|
-
bindingState,
|
|
947
|
-
smPipelineHandle,
|
|
948
|
-
instanceDraws,
|
|
949
|
-
entry.mesh.indexed,
|
|
950
|
-
sm.indexCount,
|
|
951
|
-
sm.vertexCount,
|
|
952
|
-
sm.indexOffset,
|
|
953
|
-
);
|
|
954
|
-
} else {
|
|
955
|
-
profileGeometrySegment(c, passKind, 'draw-submit', () =>
|
|
1009
|
+
recordOcclusionCandidate(() =>
|
|
956
1010
|
submitSubmeshDraws(
|
|
957
1011
|
pass,
|
|
958
1012
|
bindingState,
|
|
@@ -964,6 +1018,21 @@ export function recordGeometryDraws(
|
|
|
964
1018
|
sm.indexOffset,
|
|
965
1019
|
),
|
|
966
1020
|
);
|
|
1021
|
+
} else {
|
|
1022
|
+
profileGeometrySegment(c, passKind, 'draw-submit', () =>
|
|
1023
|
+
recordOcclusionCandidate(() =>
|
|
1024
|
+
submitSubmeshDraws(
|
|
1025
|
+
pass,
|
|
1026
|
+
bindingState,
|
|
1027
|
+
smPipelineHandle,
|
|
1028
|
+
instanceDraws,
|
|
1029
|
+
entry.mesh.indexed,
|
|
1030
|
+
sm.indexCount,
|
|
1031
|
+
sm.vertexCount,
|
|
1032
|
+
sm.indexOffset,
|
|
1033
|
+
),
|
|
1034
|
+
),
|
|
1035
|
+
);
|
|
967
1036
|
}
|
|
968
1037
|
}
|
|
969
1038
|
}
|
|
@@ -978,10 +1047,35 @@ function resolveGeometryInstanceBuffer(
|
|
|
978
1047
|
c: _InternalRenderPipelineContext,
|
|
979
1048
|
entry: _InternalRenderPipelineContext['validatedOrdered'][number],
|
|
980
1049
|
identityInstanceDraws: readonly GeometryInstanceDraw[],
|
|
1050
|
+
useProbeBlend: boolean,
|
|
981
1051
|
): readonly GeometryInstanceDraw[] | null {
|
|
982
1052
|
const { runtime, pipelineState, frameState } = c;
|
|
983
1053
|
const inst = entry.source.instances;
|
|
984
|
-
|
|
1054
|
+
const probeBinding =
|
|
1055
|
+
!useProbeBlend ||
|
|
1056
|
+
!runtime.device.caps.storageBuffer ||
|
|
1057
|
+
entry.source.probeBlendRecord === undefined
|
|
1058
|
+
? undefined
|
|
1059
|
+
: resolveProbeBlendBuffer(
|
|
1060
|
+
c,
|
|
1061
|
+
entry.source.probeBlendRecord,
|
|
1062
|
+
worldEntityKey(entry.source.worldId, entry.source.entityKey),
|
|
1063
|
+
);
|
|
1064
|
+
if (inst === undefined) {
|
|
1065
|
+
const identity = identityInstanceDraws[0];
|
|
1066
|
+
if (identity === undefined) return null;
|
|
1067
|
+
return [
|
|
1068
|
+
{
|
|
1069
|
+
...identity,
|
|
1070
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(
|
|
1071
|
+
c,
|
|
1072
|
+
pipelineState.identityInstanceBuffer,
|
|
1073
|
+
probeBinding?.buffer,
|
|
1074
|
+
),
|
|
1075
|
+
probeOffset: probeBinding?.offset ?? -1,
|
|
1076
|
+
},
|
|
1077
|
+
];
|
|
1078
|
+
}
|
|
985
1079
|
// A present, empty Instances array means zero draws. Do not fall back to
|
|
986
1080
|
// the shared identity buffer, which would silently render one instance.
|
|
987
1081
|
if (inst.instanceCount === 0) return [];
|
|
@@ -1022,7 +1116,12 @@ function resolveGeometryInstanceBuffer(
|
|
|
1022
1116
|
}
|
|
1023
1117
|
draws.push({
|
|
1024
1118
|
instanceBuffer: buffer.handle,
|
|
1025
|
-
instanceBindGroup: resolveGeometryInstancesBindGroup(
|
|
1119
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(
|
|
1120
|
+
c,
|
|
1121
|
+
buffer.handle,
|
|
1122
|
+
probeBinding?.buffer,
|
|
1123
|
+
),
|
|
1124
|
+
probeOffset: probeBinding?.offset ?? -1,
|
|
1026
1125
|
instanceCount: count,
|
|
1027
1126
|
});
|
|
1028
1127
|
}
|
|
@@ -1114,25 +1213,80 @@ function resolveGeometryInstanceBuffer(
|
|
|
1114
1213
|
return [
|
|
1115
1214
|
{
|
|
1116
1215
|
instanceBuffer,
|
|
1117
|
-
instanceBindGroup: resolveGeometryInstancesBindGroup(c, instanceBuffer),
|
|
1216
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(c, instanceBuffer, probeBinding?.buffer),
|
|
1217
|
+
probeOffset: probeBinding?.offset ?? -1,
|
|
1118
1218
|
instanceCount,
|
|
1119
1219
|
},
|
|
1120
1220
|
];
|
|
1121
1221
|
}
|
|
1122
1222
|
|
|
1123
|
-
function
|
|
1223
|
+
export function resolveProbeBlendBuffer(
|
|
1224
|
+
c: _InternalRenderPipelineContext,
|
|
1225
|
+
record: import('../scene/probe-blend-record').ProbeBlendRecord | undefined,
|
|
1226
|
+
entityKey?: number,
|
|
1227
|
+
): { readonly buffer: Buffer; readonly offset: number } {
|
|
1228
|
+
const { runtime, frameState } = c;
|
|
1229
|
+
const usage = runtime.device.caps.storageBuffer
|
|
1230
|
+
? GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST
|
|
1231
|
+
: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
|
|
1232
|
+
if (record === undefined) throw new Error('probe blend record is required for probe allocation');
|
|
1233
|
+
if (entityKey === undefined) throw new Error('probe blend record requires an entity key');
|
|
1234
|
+
const offset = probeBlendRecordOffset(record.objectKey);
|
|
1235
|
+
const requiredCapacity = record.objectKey + 2;
|
|
1236
|
+
let buffer = frameState.probeBlendRecordBuffer;
|
|
1237
|
+
if (buffer === undefined || frameState.probeBlendRecordBufferCapacity < requiredCapacity) {
|
|
1238
|
+
const created = runtime.device.createBuffer({
|
|
1239
|
+
label: 'probe-blend-records',
|
|
1240
|
+
size: requiredCapacity * PROBE_BLEND_RECORD_STRIDE,
|
|
1241
|
+
usage,
|
|
1242
|
+
mappedAtCreation: false,
|
|
1243
|
+
});
|
|
1244
|
+
if (!created.ok) throw created.error;
|
|
1245
|
+
buffer = new GpuBuffer(runtime.device, created.value);
|
|
1246
|
+
frameState.probeBlendRecordBuffer = buffer;
|
|
1247
|
+
frameState.probeBlendRecordBufferCapacity = requiredCapacity;
|
|
1248
|
+
// The cache is tied to the previous backing allocation. A new buffer has
|
|
1249
|
+
// no valid record contents, so every later object must upload its full
|
|
1250
|
+
// 160B payload even when generation/bytes match the old allocation.
|
|
1251
|
+
frameState.probeBlendBuffers.clear();
|
|
1252
|
+
}
|
|
1253
|
+
const cached = frameState.probeBlendBuffers.get(entityKey);
|
|
1254
|
+
const unchanged =
|
|
1255
|
+
cached !== undefined &&
|
|
1256
|
+
cached.generation === record.generation &&
|
|
1257
|
+
cached.bytes.length === record.bytes.length &&
|
|
1258
|
+
cached.bytes.every((value, index) => value === record.bytes[index]);
|
|
1259
|
+
if (!unchanged) {
|
|
1260
|
+
const uploaded = runtime.device.queue.writeBuffer(buffer.handle, offset, record.bytes);
|
|
1261
|
+
if (!uploaded.ok) throw uploaded.error;
|
|
1262
|
+
// Publish the generation only after the complete 160B queue write succeeds.
|
|
1263
|
+
frameState.probeBlendBuffers.set(entityKey, {
|
|
1264
|
+
generation: record.generation,
|
|
1265
|
+
bytes: new Uint8Array(record.bytes),
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
return { buffer: buffer.handle, offset };
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
export function resolveGeometryInstancesBindGroup(
|
|
1124
1272
|
c: _InternalRenderPipelineContext,
|
|
1125
1273
|
instanceBuffer: Buffer,
|
|
1274
|
+
probeBuffer?: Buffer,
|
|
1126
1275
|
): BindGroup {
|
|
1127
1276
|
const { runtime, pipelineState, frameState, bindGroupCounts } = c;
|
|
1277
|
+
const layout =
|
|
1278
|
+
probeBuffer === undefined
|
|
1279
|
+
? pipelineState.instancesBindGroupLayout
|
|
1280
|
+
: pipelineState.probeInstancesBindGroupLayout;
|
|
1281
|
+
if (layout === undefined) throw new Error('probe instances bind-group layout is unavailable');
|
|
1128
1282
|
return getOrCreateFromChain(
|
|
1129
1283
|
frameState.instancesBgShared,
|
|
1130
|
-
[
|
|
1131
|
-
'instances',
|
|
1284
|
+
probeBuffer === undefined ? [layout, instanceBuffer] : [layout, instanceBuffer, probeBuffer],
|
|
1285
|
+
probeBuffer === undefined ? 'instances-no-probe' : 'instances-probe',
|
|
1132
1286
|
() => {
|
|
1133
1287
|
const result = runtime.device.createBindGroup({
|
|
1134
1288
|
label: 'pbr-instances-bg',
|
|
1135
|
-
layout
|
|
1289
|
+
layout,
|
|
1136
1290
|
entries: [
|
|
1137
1291
|
{
|
|
1138
1292
|
binding: 0,
|
|
@@ -1141,6 +1295,17 @@ function resolveGeometryInstancesBindGroup(
|
|
|
1141
1295
|
value: { buffer: instanceBuffer },
|
|
1142
1296
|
},
|
|
1143
1297
|
},
|
|
1298
|
+
...(probeBuffer === undefined
|
|
1299
|
+
? []
|
|
1300
|
+
: [
|
|
1301
|
+
{
|
|
1302
|
+
binding: 1,
|
|
1303
|
+
resource: {
|
|
1304
|
+
kind: 'buffer' as const,
|
|
1305
|
+
value: { buffer: probeBuffer, offset: 0, size: PROBE_BLEND_RECORD_BYTE_SIZE },
|
|
1306
|
+
},
|
|
1307
|
+
},
|
|
1308
|
+
]),
|
|
1144
1309
|
],
|
|
1145
1310
|
});
|
|
1146
1311
|
if (!result.ok) throw result.error;
|
|
@@ -441,6 +441,13 @@ export interface StandardReflectionProbeMaterialProjection {
|
|
|
441
441
|
readonly fallbackToSkylight: boolean;
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
+
/** Keeps the fallback output as a same-pass, linear-HDR material projection. */
|
|
445
|
+
export function standardPbrFallbackDemand(
|
|
446
|
+
projection: StandardReflectionProbeMaterialProjection,
|
|
447
|
+
): boolean {
|
|
448
|
+
return projection.probeIndex !== undefined || projection.fallbackToSkylight;
|
|
449
|
+
}
|
|
450
|
+
|
|
444
451
|
/** Projects the selected scene row into the Standard material lane. */
|
|
445
452
|
export function projectReflectionProbeMaterialBinding(
|
|
446
453
|
binding: StandardReflectionProbeBinding,
|
|
@@ -662,7 +669,7 @@ export function defaultViewForUserRegionField(
|
|
|
662
669
|
* `renderableIndex` per RenderSystem lifetime via the `seenIndices` Set
|
|
663
670
|
* (the same warn-once anchor pattern used for missing-texture sprites).
|
|
664
671
|
*
|
|
665
|
-
* @param transformWorld The entity's resolved
|
|
672
|
+
* @param transformWorld The entity's resolved GlobalTransform.world mat4 (16 floats column-major).
|
|
666
673
|
* @param slices The four anchor distances `[left, top, right, bottom]`
|
|
667
674
|
* (sentinel `bottom < 0` for tile mode is consumed via abs()).
|
|
668
675
|
* @param renderableIndex The entity index into the validated renderables list.
|
|
@@ -25,7 +25,10 @@ import {
|
|
|
25
25
|
} from '../ibl/skylight-bind-group';
|
|
26
26
|
import type { InstanceBufferCacheEntry } from '../instance-buffer-cache';
|
|
27
27
|
import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from '../materials';
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
isStandardPbrMaterialShader,
|
|
30
|
+
SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET,
|
|
31
|
+
} from '../pbr-pipeline';
|
|
29
32
|
import {
|
|
30
33
|
buildBeginRenderPassDescriptor,
|
|
31
34
|
standardTopologyVariantSet,
|
|
@@ -33,6 +36,7 @@ import {
|
|
|
33
36
|
} from '../pipeline-spec';
|
|
34
37
|
import type { MaterialSnapshot, SpriteInstancesSnapshot } from '../render-system-extract';
|
|
35
38
|
import { worldEntityKey } from './frame-snapshot';
|
|
39
|
+
import { resolveGeometryInstancesBindGroup, resolveProbeBlendBuffer } from './main-pass-geometry';
|
|
36
40
|
import {
|
|
37
41
|
BUILTIN_USER_REGION_TEXTURE_FIELDS,
|
|
38
42
|
defaultViewForUserRegionField,
|
|
@@ -463,7 +467,7 @@ function recordSpriteTransparentPbrDraws(
|
|
|
463
467
|
) => BindGroup,
|
|
464
468
|
meshGroup2: BindGroup | null,
|
|
465
469
|
): void {
|
|
466
|
-
const { runtime, pipelineState,
|
|
470
|
+
const { runtime, pipelineState, validatedOrdered } = c;
|
|
467
471
|
const isHdrTarget =
|
|
468
472
|
c.tonemapActive || transparentPassColorFormat(c, pipelineState) === 'rgba16float';
|
|
469
473
|
let lastPbrSubPipelineHandle: typeof pipelineState.unlitPipeline = null;
|
|
@@ -497,48 +501,6 @@ function recordSpriteTransparentPbrDraws(
|
|
|
497
501
|
spritePass.setIndexBuffer(entry.mesh.indexBuffer.handle, entry.mesh.indexFormat);
|
|
498
502
|
lastPbrSubIndexBuffer = entry.mesh.indexBuffer;
|
|
499
503
|
}
|
|
500
|
-
// Identity instance BG (instanceCount=1); reuse the per-entity cache.
|
|
501
|
-
const identityInstBg: BindGroup = getOrCreatePerEntity(
|
|
502
|
-
frameState.instancesBgPerEntity,
|
|
503
|
-
worldEntityKey(entry.source.worldId, entry.source.entityKey),
|
|
504
|
-
[pipelineState.identityInstanceBuffer],
|
|
505
|
-
'instances',
|
|
506
|
-
() => {
|
|
507
|
-
const result = runtime.device.createBindGroup({
|
|
508
|
-
label: 'pbr-transparent-sub-instances-bg',
|
|
509
|
-
layout: pipelineState.instancesBindGroupLayout,
|
|
510
|
-
entries: [
|
|
511
|
-
{
|
|
512
|
-
binding: 0,
|
|
513
|
-
resource: {
|
|
514
|
-
kind: 'buffer',
|
|
515
|
-
value: { buffer: pipelineState.identityInstanceBuffer },
|
|
516
|
-
},
|
|
517
|
-
},
|
|
518
|
-
],
|
|
519
|
-
});
|
|
520
|
-
if (!result.ok) throw result.error;
|
|
521
|
-
return result.value;
|
|
522
|
-
},
|
|
523
|
-
bindGroupCounts,
|
|
524
|
-
);
|
|
525
|
-
spritePass.setBindGroup(3, identityInstBg);
|
|
526
|
-
|
|
527
|
-
const subVariantSet = standardTopologyVariantSet(
|
|
528
|
-
c.standardLighting,
|
|
529
|
-
runtime.device.caps.storageBuffer,
|
|
530
|
-
entry.mesh.layoutProjection.attributes.some((attribute) => attribute.key === 'color'),
|
|
531
|
-
);
|
|
532
|
-
const projectionVariantSetResult = variantSetFromVertexLayoutProjection(
|
|
533
|
-
entry.mesh.layoutProjection,
|
|
534
|
-
subVariantSet,
|
|
535
|
-
);
|
|
536
|
-
if (!projectionVariantSetResult.ok) {
|
|
537
|
-
runtime.errorRegistry.fire(projectionVariantSetResult.error);
|
|
538
|
-
continue;
|
|
539
|
-
}
|
|
540
|
-
const projectionVariantSet = projectionVariantSetResult.value;
|
|
541
|
-
|
|
542
504
|
for (let smIdx = 0; smIdx < entry.mesh.submeshes.length; smIdx++) {
|
|
543
505
|
const sm = entry.mesh.submeshes[smIdx];
|
|
544
506
|
if (sm === undefined) continue;
|
|
@@ -549,6 +511,39 @@ function recordSpriteTransparentPbrDraws(
|
|
|
549
511
|
if (submeshMaterial.transparent !== true) continue;
|
|
550
512
|
const smShaderId = submeshMaterial.materialShaderId;
|
|
551
513
|
if (smShaderId === undefined) continue;
|
|
514
|
+
const probeBlendAvailable =
|
|
515
|
+
runtime.device.caps.storageBuffer &&
|
|
516
|
+
entry.source.probeBlendRecord !== undefined &&
|
|
517
|
+
isStandardPbrMaterialShader(smShaderId);
|
|
518
|
+
const probeBinding = probeBlendAvailable
|
|
519
|
+
? resolveProbeBlendBuffer(
|
|
520
|
+
c,
|
|
521
|
+
entry.source.probeBlendRecord,
|
|
522
|
+
worldEntityKey(entry.source.worldId, entry.source.entityKey),
|
|
523
|
+
)
|
|
524
|
+
: undefined;
|
|
525
|
+
const identityInstBg = resolveGeometryInstancesBindGroup(
|
|
526
|
+
c,
|
|
527
|
+
pipelineState.identityInstanceBuffer,
|
|
528
|
+
probeBinding?.buffer,
|
|
529
|
+
);
|
|
530
|
+
if (probeBinding === undefined) spritePass.setBindGroup(3, identityInstBg);
|
|
531
|
+
else spritePass.setBindGroup(3, identityInstBg, [probeBinding.offset]);
|
|
532
|
+
const subVariantSet = standardTopologyVariantSet(
|
|
533
|
+
c.standardLighting,
|
|
534
|
+
runtime.device.caps.storageBuffer,
|
|
535
|
+
entry.mesh.layoutProjection.attributes.some((attribute) => attribute.key === 'color'),
|
|
536
|
+
probeBlendAvailable,
|
|
537
|
+
);
|
|
538
|
+
const projectionVariantSetResult = variantSetFromVertexLayoutProjection(
|
|
539
|
+
entry.mesh.layoutProjection,
|
|
540
|
+
subVariantSet,
|
|
541
|
+
);
|
|
542
|
+
if (!projectionVariantSetResult.ok) {
|
|
543
|
+
runtime.errorRegistry.fire(projectionVariantSetResult.error);
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
const projectionVariantSet = projectionVariantSetResult.value;
|
|
552
547
|
const subPipelineEntry =
|
|
553
548
|
c.runtime.getMaterialShaderPipelineEntry?.(
|
|
554
549
|
smShaderId,
|
|
@@ -837,21 +832,15 @@ function recordSpriteEntityDraws(
|
|
|
837
832
|
);
|
|
838
833
|
spriteInstanceCount = spriteInst.instanceCount;
|
|
839
834
|
spriteInstanceBuffer = pipelineState.identityInstanceBuffer;
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
},
|
|
850
|
-
},
|
|
851
|
-
],
|
|
852
|
-
});
|
|
853
|
-
if (!spriteInstBgResult.ok) throw spriteInstBgResult.error;
|
|
854
|
-
spritePass.setBindGroup(3, spriteInstBgResult.value as BindGroup);
|
|
835
|
+
// Sprite shaders do not declare the Standard PBR Probe ABI. A
|
|
836
|
+
// retained scene record must therefore not change their group(3)
|
|
837
|
+
// bind-group shape.
|
|
838
|
+
const spriteInstBg = resolveGeometryInstancesBindGroup(
|
|
839
|
+
c,
|
|
840
|
+
spriteInstanceBuffer,
|
|
841
|
+
undefined,
|
|
842
|
+
);
|
|
843
|
+
spritePass.setBindGroup(3, spriteInstBg);
|
|
855
844
|
spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
|
|
856
845
|
continue;
|
|
857
846
|
}
|
|
@@ -959,32 +948,10 @@ function recordSpriteEntityDraws(
|
|
|
959
948
|
? c.hdrpClusterBindGroup
|
|
960
949
|
: meshBindGroup;
|
|
961
950
|
|
|
962
|
-
// M3 / w12: LDR sprite split pass per-entity instances BG cache.
|
|
963
|
-
//
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
worldEntityKey(spriteEntry.source.worldId, spriteEntry.source.entityKey),
|
|
967
|
-
[spriteInstanceBuffer],
|
|
968
|
-
'instances',
|
|
969
|
-
() => {
|
|
970
|
-
const result = runtime.device.createBindGroup({
|
|
971
|
-
label: 'sprite-pass-instances-bg',
|
|
972
|
-
layout: pipelineState.instancesBindGroupLayout,
|
|
973
|
-
entries: [
|
|
974
|
-
{
|
|
975
|
-
binding: 0,
|
|
976
|
-
resource: {
|
|
977
|
-
kind: 'buffer',
|
|
978
|
-
value: { buffer: spriteInstanceBuffer },
|
|
979
|
-
},
|
|
980
|
-
},
|
|
981
|
-
],
|
|
982
|
-
});
|
|
983
|
-
if (!result.ok) throw result.error;
|
|
984
|
-
return result.value;
|
|
985
|
-
},
|
|
986
|
-
bindGroupCounts,
|
|
987
|
-
);
|
|
951
|
+
// M3 / w12: LDR sprite split pass per-entity instances BG cache. Sprite
|
|
952
|
+
// shaders do not declare the Standard PBR Probe ABI, so retained probe
|
|
953
|
+
// records stay out of this bind-group path.
|
|
954
|
+
const spriteInstancesBg = resolveGeometryInstancesBindGroup(c, spriteInstanceBuffer, undefined);
|
|
988
955
|
|
|
989
956
|
spritePass.setBindGroup(2, spriteGroup2 as BindGroup, [i * MESH_PER_ENTITY_STRIDE]);
|
|
990
957
|
|