@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
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
RhiError,
|
|
11
11
|
type RhiRenderPassEncoder,
|
|
12
12
|
} from '@forgeax/engine-rhi';
|
|
13
|
-
import type { PassKind, PrimitiveTopology } from '@forgeax/engine-types';
|
|
13
|
+
import type { ParamSchemaEntry, PassKind, PrimitiveTopology } from '@forgeax/engine-types';
|
|
14
14
|
import { GpuBuffer } from '../gpu-resource';
|
|
15
15
|
import {
|
|
16
16
|
GPU_BUFFER_USAGE_COPY_DST,
|
|
@@ -22,7 +22,12 @@ import type { InstanceBufferCacheEntry } from '../instance-buffer-cache';
|
|
|
22
22
|
import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from '../materials';
|
|
23
23
|
import {
|
|
24
24
|
createPbrSkinMeshBindGroupEntries,
|
|
25
|
+
isCanonicalStandardPbrMaterialShader,
|
|
26
|
+
isStandardPbrMaterialShader,
|
|
27
|
+
isStandardPbrSkinMaterialShader,
|
|
28
|
+
materialBindGroupLayoutIdentity,
|
|
25
29
|
pbrSkinMeshDynamicOffsets,
|
|
30
|
+
physicalTextureFields,
|
|
26
31
|
SKIN_MATERIAL_SHADER_ID,
|
|
27
32
|
} from '../pbr-pipeline';
|
|
28
33
|
import {
|
|
@@ -35,7 +40,12 @@ import type { PointsLinesRecordPlan } from '../points-lines/record';
|
|
|
35
40
|
import { POINTS_LINES_MATERIAL_SHADER_ID } from '../points-lines/record';
|
|
36
41
|
import type { RenderRecordPhase } from '../render-contract';
|
|
37
42
|
import type { MaterialSnapshot } from '../render-system-extract';
|
|
38
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
PROBE_BLEND_RECORD_BYTE_SIZE,
|
|
45
|
+
PROBE_BLEND_RECORD_STRIDE,
|
|
46
|
+
probeBlendRecordOffset,
|
|
47
|
+
} from '../scene/probe-blend-record';
|
|
48
|
+
import { getOpaqueResourceIdentity, worldEntityKey } from './frame-snapshot';
|
|
39
49
|
import {
|
|
40
50
|
geometryRenderStateForTopology,
|
|
41
51
|
isEntityFullyTransparent,
|
|
@@ -58,14 +68,29 @@ import { POINTS_LINES_VIEW_SLOT_STRIDE, writePointsLinesViewUbo } from './view-u
|
|
|
58
68
|
type GeometryInstanceDraw = {
|
|
59
69
|
readonly instanceBuffer: Buffer;
|
|
60
70
|
readonly instanceBindGroup: BindGroup;
|
|
71
|
+
/** -1 means the no-probe layout and therefore no dynamic offset. */
|
|
72
|
+
readonly probeOffset: number;
|
|
61
73
|
readonly instanceCount: number;
|
|
62
74
|
};
|
|
63
75
|
|
|
64
76
|
type GeometryBindingState = {
|
|
65
77
|
pipeline: RenderPipeline | null;
|
|
66
78
|
instancesBuffer: Buffer | null;
|
|
79
|
+
probeOffset: number;
|
|
67
80
|
};
|
|
68
81
|
|
|
82
|
+
function materialDiagnosticsEnabled(): boolean {
|
|
83
|
+
if (typeof globalThis !== 'object' || globalThis === null || !('process' in globalThis)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const processValue = (
|
|
87
|
+
globalThis as {
|
|
88
|
+
readonly process?: { readonly env?: Record<string, string | undefined> };
|
|
89
|
+
}
|
|
90
|
+
).process;
|
|
91
|
+
return processValue?.env?.FORGEAX_MATERIAL_DIAGNOSTICS === '1';
|
|
92
|
+
}
|
|
93
|
+
|
|
69
94
|
type MaterialPipelineLookup = {
|
|
70
95
|
readonly materialShaderId: string;
|
|
71
96
|
readonly isHdrTarget: boolean;
|
|
@@ -77,6 +102,7 @@ type MaterialPipelineLookup = {
|
|
|
77
102
|
readonly layoutProjection: import('@forgeax/engine-geometry').VertexLayoutProjection;
|
|
78
103
|
readonly sampleCount: number;
|
|
79
104
|
readonly colorFormatOverride: GPUTextureFormat | undefined;
|
|
105
|
+
readonly additionalColorFormats: readonly GPUTextureFormat[] | undefined;
|
|
80
106
|
readonly handle: MaterialShaderPipelineEntry | null;
|
|
81
107
|
};
|
|
82
108
|
|
|
@@ -84,6 +110,121 @@ type GeometryRecordProfileSegment = 'material-bind-groups' | 'pipeline-selection
|
|
|
84
110
|
|
|
85
111
|
type GeometryRenderState = ReturnType<typeof geometryRenderStateForTopology>;
|
|
86
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Select the transmission shader axis from authored material data, not the
|
|
115
|
+
* canonical boot schema. The latter reserves transmission fields for the
|
|
116
|
+
* shared Standard ABI even when a material remains base-only.
|
|
117
|
+
*/
|
|
118
|
+
export function requestsStandardTransmissionVariant(
|
|
119
|
+
material: Pick<MaterialSnapshot, 'materialShaderId' | 'paramSnapshot'>,
|
|
120
|
+
): boolean {
|
|
121
|
+
return (
|
|
122
|
+
material.materialShaderId === 'forgeax::default-standard-pbr' &&
|
|
123
|
+
material.paramSnapshot?.transmission !== undefined
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function recordIblPipelineBinding(
|
|
128
|
+
c: _InternalRenderPipelineContext,
|
|
129
|
+
material: MaterialSnapshot,
|
|
130
|
+
pipeline: RenderPipeline,
|
|
131
|
+
materialGroup: BindGroup,
|
|
132
|
+
): void {
|
|
133
|
+
const receipt = c.frameState.iblBindingInspection;
|
|
134
|
+
if (receipt === undefined || !isStandardPbrMaterialShader(material.materialShaderId)) return;
|
|
135
|
+
const materialBgl =
|
|
136
|
+
c.runtime.getMaterialBindGroupLayout?.(
|
|
137
|
+
material.materialShaderId ?? 'forgeax::default-standard-pbr',
|
|
138
|
+
) ?? c.pipelineState.materialBindGroupLayout;
|
|
139
|
+
c.frameState.iblBindingInspection = {
|
|
140
|
+
...receipt,
|
|
141
|
+
pipeline: {
|
|
142
|
+
pipelineIdentity: getOpaqueResourceIdentity(pipeline as object),
|
|
143
|
+
effectiveMaterialLayoutIdentity: effectiveMaterialLayoutIdentity(
|
|
144
|
+
material.materialShaderId ?? 'forgeax::default-standard-pbr',
|
|
145
|
+
material.materialParamSchema,
|
|
146
|
+
),
|
|
147
|
+
materialBglIdentity: getOpaqueResourceIdentity(materialBgl as object),
|
|
148
|
+
bindGroupIdentity: getOpaqueResourceIdentity(materialGroup as object),
|
|
149
|
+
drawFrameId: c.frameState.frameNumber,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
const materialReceipt = c.frameState.iblBindingInspection.material;
|
|
153
|
+
const errors: string[] = [];
|
|
154
|
+
if (
|
|
155
|
+
materialReceipt !== undefined &&
|
|
156
|
+
materialReceipt.materialBglIdentity !== getOpaqueResourceIdentity(materialBgl as object)
|
|
157
|
+
) {
|
|
158
|
+
errors.push('material-pipeline-bgl-identity-mismatch');
|
|
159
|
+
}
|
|
160
|
+
if (
|
|
161
|
+
materialReceipt !== undefined &&
|
|
162
|
+
materialReceipt.bindGroupIdentity !== getOpaqueResourceIdentity(materialGroup as object)
|
|
163
|
+
) {
|
|
164
|
+
errors.push('material-bind-group-identity-mismatch');
|
|
165
|
+
}
|
|
166
|
+
if (materialReceipt !== undefined) {
|
|
167
|
+
const expectedResourceIdentities = [
|
|
168
|
+
receipt.resources.irradiance.viewIdentity,
|
|
169
|
+
receipt.resources.irradiance.samplerIdentity,
|
|
170
|
+
receipt.resources.prefilter.viewIdentity,
|
|
171
|
+
receipt.resources.prefilter.samplerIdentity,
|
|
172
|
+
receipt.resources.brdfLut.viewIdentity,
|
|
173
|
+
receipt.resources.brdfLut.samplerIdentity,
|
|
174
|
+
receipt.resources.intensityBufferIdentity,
|
|
175
|
+
];
|
|
176
|
+
const actualResourceIdentities = materialReceipt.entries
|
|
177
|
+
.filter((entry) => entry.binding >= materialReceipt.skylightBindingStart)
|
|
178
|
+
.slice(0, expectedResourceIdentities.length)
|
|
179
|
+
.map((entry) => entry.resourceIdentity);
|
|
180
|
+
if (
|
|
181
|
+
actualResourceIdentities.length !== expectedResourceIdentities.length ||
|
|
182
|
+
actualResourceIdentities.some(
|
|
183
|
+
(identity, index) => identity !== expectedResourceIdentities[index],
|
|
184
|
+
)
|
|
185
|
+
) {
|
|
186
|
+
errors.push('material-ibl-resource-identity-mismatch');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
c.frameState.iblBindingInspection = {
|
|
190
|
+
...c.frameState.iblBindingInspection,
|
|
191
|
+
status: errors.length === 0 ? 'binding-chain-consistent' : 'binding-chain-mismatch',
|
|
192
|
+
errors,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const SHARED_BOOT_MATERIAL_SHADER_IDS = new Set([
|
|
197
|
+
'forgeax::default-unlit',
|
|
198
|
+
'forgeax::default-shadow-caster',
|
|
199
|
+
'forgeax::sprite',
|
|
200
|
+
'forgeax::sprite-lit',
|
|
201
|
+
'forgeax::default-sprite',
|
|
202
|
+
'forgeax::msdf-text',
|
|
203
|
+
'forgeax::default-standard-pbr',
|
|
204
|
+
'forgeax::pbr-skin',
|
|
205
|
+
'forgeax::default-standard-pbr-skin',
|
|
206
|
+
]);
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Returns the layout identity that can distinguish a material PSO in the
|
|
210
|
+
* record cache. Shared boot shaders keep the boot layout identity even when a
|
|
211
|
+
* manifest exposes a schema; Standard PBR only opts into a schema-derived
|
|
212
|
+
* identity when authored clearcoat texture bindings extend that layout.
|
|
213
|
+
*/
|
|
214
|
+
export function effectiveMaterialLayoutIdentity(
|
|
215
|
+
materialShaderId: string,
|
|
216
|
+
materialParamSchema?: readonly ParamSchemaEntry[],
|
|
217
|
+
): string | undefined {
|
|
218
|
+
if (materialParamSchema === undefined) return undefined;
|
|
219
|
+
const hasStandardPhysicalMaps =
|
|
220
|
+
isStandardPbrMaterialShader(materialShaderId) &&
|
|
221
|
+
physicalTextureFields(materialParamSchema).length > 0;
|
|
222
|
+
if (SHARED_BOOT_MATERIAL_SHADER_IDS.has(materialShaderId) && !hasStandardPhysicalMaps) {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
return materialBindGroupLayoutIdentity(materialShaderId, materialParamSchema);
|
|
226
|
+
}
|
|
227
|
+
|
|
87
228
|
/**
|
|
88
229
|
* Resolve the depth contract for a geometry pass without changing the base
|
|
89
230
|
* material state. Temporal scene-data shares the main pass depth attachment:
|
|
@@ -138,9 +279,17 @@ function submitSubmeshDraws(
|
|
|
138
279
|
state.pipeline = pipeline;
|
|
139
280
|
}
|
|
140
281
|
for (const instanceDraw of instanceDraws) {
|
|
141
|
-
if (
|
|
142
|
-
|
|
282
|
+
if (
|
|
283
|
+
instanceDraw.instanceBuffer !== state.instancesBuffer ||
|
|
284
|
+
instanceDraw.probeOffset !== state.probeOffset
|
|
285
|
+
) {
|
|
286
|
+
if (instanceDraw.probeOffset < 0) {
|
|
287
|
+
pass.setBindGroup(3, instanceDraw.instanceBindGroup);
|
|
288
|
+
} else {
|
|
289
|
+
pass.setBindGroup(3, instanceDraw.instanceBindGroup, [instanceDraw.probeOffset]);
|
|
290
|
+
}
|
|
143
291
|
state.instancesBuffer = instanceDraw.instanceBuffer;
|
|
292
|
+
state.probeOffset = instanceDraw.probeOffset;
|
|
144
293
|
}
|
|
145
294
|
if (indexed) {
|
|
146
295
|
pass.drawIndexed(indexCount, instanceDraw.instanceCount, indexOffset, 0, 0);
|
|
@@ -210,6 +359,7 @@ export function recordGeometryDraws(
|
|
|
210
359
|
viewBindGroup,
|
|
211
360
|
viewBindGroupDynamicOffset = 0,
|
|
212
361
|
} = c;
|
|
362
|
+
const diagnosticsEnabled = materialDiagnosticsEnabled();
|
|
213
363
|
const colorFormatOverride = c.transparentColorFormat as GPUTextureFormat | undefined;
|
|
214
364
|
// The prepared Standard topology is the frame authority. A bind-group
|
|
215
365
|
// identity is only a resource result; using it to infer the shader lane
|
|
@@ -226,12 +376,14 @@ export function recordGeometryDraws(
|
|
|
226
376
|
const bindingState: GeometryBindingState = {
|
|
227
377
|
pipeline: null,
|
|
228
378
|
instancesBuffer: null,
|
|
379
|
+
probeOffset: -1,
|
|
229
380
|
};
|
|
230
381
|
const identityInstanceBuffer = pipelineState.identityInstanceBuffer;
|
|
231
382
|
const identityInstanceDraws: readonly GeometryInstanceDraw[] = [
|
|
232
383
|
{
|
|
233
384
|
instanceBuffer: identityInstanceBuffer,
|
|
234
|
-
instanceBindGroup: resolveGeometryInstancesBindGroup(c, identityInstanceBuffer),
|
|
385
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(c, identityInstanceBuffer, undefined),
|
|
386
|
+
probeOffset: -1,
|
|
235
387
|
instanceCount: 1,
|
|
236
388
|
},
|
|
237
389
|
];
|
|
@@ -253,6 +405,9 @@ export function recordGeometryDraws(
|
|
|
253
405
|
// renderer's authoritative cache still owns lifetime/invalidation, while
|
|
254
406
|
// this frame-local table removes the hot call/lookup overhead.
|
|
255
407
|
const materialPipelineLookupCache = new Map<string, Map<string, MaterialPipelineLookup[]>>();
|
|
408
|
+
const recordOcclusionCandidate = (draw: () => void): void => {
|
|
409
|
+
draw();
|
|
410
|
+
};
|
|
256
411
|
const resolveMaterialPipeline = (
|
|
257
412
|
materialShaderId: string,
|
|
258
413
|
renderState: MaterialSnapshot['renderState'],
|
|
@@ -262,6 +417,19 @@ export function recordGeometryDraws(
|
|
|
262
417
|
colorFormat: GPUTextureFormat | undefined,
|
|
263
418
|
layoutProjection: import('@forgeax/engine-geometry').VertexLayoutProjection,
|
|
264
419
|
): MaterialShaderPipelineEntry | null => {
|
|
420
|
+
// The fallback MRT is an extension of the built-in Standard PBR output
|
|
421
|
+
// contract only. The render pass may carry a second attachment whenever
|
|
422
|
+
// another renderable needs S_fallback, but shaders such as unlit, sprite,
|
|
423
|
+
// and the skin PBR variant still expose only @location(0). Passing that
|
|
424
|
+
// attachment into their PSO would make WebGPU reject the pipeline before
|
|
425
|
+
// the first draw ("Color target has no corresponding fragment stage
|
|
426
|
+
// output"). Keep the graph attachment shared while deriving pipeline
|
|
427
|
+
// targets from the shader's actual output contract.
|
|
428
|
+
const reflectionFallbackFormats =
|
|
429
|
+
materialShaderId === 'forgeax::default-standard-pbr' &&
|
|
430
|
+
c.reflectionFallbackColorFormat !== undefined
|
|
431
|
+
? [c.reflectionFallbackColorFormat]
|
|
432
|
+
: undefined;
|
|
265
433
|
const renderStateKey = renderStateHash(renderState);
|
|
266
434
|
const shaderLookupCache = materialPipelineLookupCache.get(materialShaderId);
|
|
267
435
|
const cachedLookups = shaderLookupCache?.get(renderStateKey);
|
|
@@ -276,7 +444,8 @@ export function recordGeometryDraws(
|
|
|
276
444
|
cached.passKind === passKind &&
|
|
277
445
|
cached.layoutProjection.digest === layoutProjection.digest &&
|
|
278
446
|
cached.sampleCount === sampleCount &&
|
|
279
|
-
cached.colorFormatOverride === colorFormat
|
|
447
|
+
cached.colorFormatOverride === colorFormat &&
|
|
448
|
+
cached.additionalColorFormats?.join(',') === reflectionFallbackFormats?.join(',')
|
|
280
449
|
) {
|
|
281
450
|
return cached.handle;
|
|
282
451
|
}
|
|
@@ -292,6 +461,12 @@ export function recordGeometryDraws(
|
|
|
292
461
|
return null;
|
|
293
462
|
}
|
|
294
463
|
const resolvedVariantSet = resolvedVariantSetResult.value;
|
|
464
|
+
const fallbackVariantSet =
|
|
465
|
+
materialShaderId !== 'forgeax::default-standard-pbr'
|
|
466
|
+
? resolvedVariantSet
|
|
467
|
+
: c.reflectionFallbackColorFormat !== undefined && resolvedVariantSet === ''
|
|
468
|
+
? ''
|
|
469
|
+
: `${resolvedVariantSet === undefined || resolvedVariantSet === '' ? '' : `${resolvedVariantSet}+`}REFLECTION_FALLBACK_AVAILABLE=${c.reflectionFallbackColorFormat !== undefined}`;
|
|
295
470
|
const resolvePipeline = () =>
|
|
296
471
|
runtime.getMaterialShaderPipelineEntry?.(
|
|
297
472
|
materialShaderId,
|
|
@@ -299,7 +474,7 @@ export function recordGeometryDraws(
|
|
|
299
474
|
renderState,
|
|
300
475
|
topology,
|
|
301
476
|
indexFormat,
|
|
302
|
-
|
|
477
|
+
fallbackVariantSet,
|
|
303
478
|
passKind,
|
|
304
479
|
undefined,
|
|
305
480
|
sampleCount,
|
|
@@ -308,6 +483,9 @@ export function recordGeometryDraws(
|
|
|
308
483
|
undefined,
|
|
309
484
|
undefined,
|
|
310
485
|
layoutProjection,
|
|
486
|
+
undefined,
|
|
487
|
+
undefined,
|
|
488
|
+
reflectionFallbackFormats,
|
|
311
489
|
) ?? null;
|
|
312
490
|
const handle =
|
|
313
491
|
profilePhase === undefined
|
|
@@ -332,6 +510,7 @@ export function recordGeometryDraws(
|
|
|
332
510
|
layoutProjection,
|
|
333
511
|
sampleCount,
|
|
334
512
|
colorFormatOverride: colorFormat,
|
|
513
|
+
additionalColorFormats: reflectionFallbackFormats,
|
|
335
514
|
handle,
|
|
336
515
|
};
|
|
337
516
|
if (shaderLookupCache === undefined) {
|
|
@@ -361,7 +540,12 @@ export function recordGeometryDraws(
|
|
|
361
540
|
|
|
362
541
|
if (
|
|
363
542
|
passKind === 'forward' &&
|
|
364
|
-
c.gpuDrivenEntityKeys.has(
|
|
543
|
+
c.gpuDrivenEntityKeys.has(
|
|
544
|
+
worldEntityKey(
|
|
545
|
+
c.gpuDrivenWorldKeys?.[entry.source.worldId] ?? entry.source.worldId,
|
|
546
|
+
entry.source.entityKey,
|
|
547
|
+
),
|
|
548
|
+
)
|
|
365
549
|
) {
|
|
366
550
|
continue;
|
|
367
551
|
}
|
|
@@ -454,12 +638,11 @@ export function recordGeometryDraws(
|
|
|
454
638
|
const pointsLinesMeshGroup = meshBindGroup ?? meshGroup2;
|
|
455
639
|
if (pointsLinesMeshGroup === null) continue;
|
|
456
640
|
pass.setBindGroup(2, pointsLinesMeshGroup, meshGroup2DynamicOffsets);
|
|
457
|
-
|
|
458
|
-
3,
|
|
641
|
+
const pointsLinesInstancesBg =
|
|
459
642
|
identityInstanceDraws[0]?.instanceBindGroup ??
|
|
460
|
-
|
|
461
|
-
);
|
|
462
|
-
recordPointsLinesDraw(pass, pointsLinesSubmission.plan);
|
|
643
|
+
resolveGeometryInstancesBindGroup(c, identityInstanceBuffer, undefined);
|
|
644
|
+
pass.setBindGroup(3, pointsLinesInstancesBg);
|
|
645
|
+
recordOcclusionCandidate(() => recordPointsLinesDraw(pass, pointsLinesSubmission.plan));
|
|
463
646
|
pass.setBindGroup(0, viewBindGroup as BindGroup, [viewBindGroupDynamicOffset, 0]);
|
|
464
647
|
continue;
|
|
465
648
|
}
|
|
@@ -487,7 +670,7 @@ export function recordGeometryDraws(
|
|
|
487
670
|
// length instead.
|
|
488
671
|
if (pipelineTag === 'unlit') dispatchCounts.unlit += 1;
|
|
489
672
|
|
|
490
|
-
const instanceDraws = resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws);
|
|
673
|
+
const instanceDraws = resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws, false);
|
|
491
674
|
if (instanceDraws === null) continue;
|
|
492
675
|
|
|
493
676
|
// feat-20260611 R2 / M8 / w28 (IS-14): skin entries need a 3-binding
|
|
@@ -518,6 +701,8 @@ export function recordGeometryDraws(
|
|
|
518
701
|
meshGroup2DynamicOffsets[0] = i * MESH_PER_ENTITY_STRIDE;
|
|
519
702
|
let group2DynamicOffsets: readonly number[] = meshGroup2DynamicOffsets;
|
|
520
703
|
const isSkinEntry = entry.source.skin !== undefined;
|
|
704
|
+
const probeBlendRecordAvailable =
|
|
705
|
+
runtime.device.caps.storageBuffer && entry.source.probeBlendRecord !== undefined;
|
|
521
706
|
// feat-20260612-skin-palette-per-frame-upload M1 / m1-3 + M6: the
|
|
522
707
|
// record stage reads the GPU buffer reference through
|
|
523
708
|
// `entry.source.skin.buffer` (per-slice carrier set at extract time
|
|
@@ -534,7 +719,22 @@ export function recordGeometryDraws(
|
|
|
534
719
|
// and walks 0, 1536, 3072, ... on the storage path.
|
|
535
720
|
const skinAllocator = pipelineState.skinPaletteAllocator;
|
|
536
721
|
const skinSlice = entry.source.skin;
|
|
537
|
-
|
|
722
|
+
// Authored Standard skin aliases deliberately publish the physical root
|
|
723
|
+
// with only their STORAGE_BUFFER capability axis. Their composed WGSL is
|
|
724
|
+
// the direct-lighting/palette (`skin`) ABI, even when the frame's
|
|
725
|
+
// canonical Standard lane uses clustered lighting. Only the canonical
|
|
726
|
+
// engine skin artifact can consume the HDRP unified skin group(2) layout;
|
|
727
|
+
// selecting it from the frame topology alone would bind
|
|
728
|
+
// `hdrp-skin-unified-bg-group2` to a three-entry URP skin PSO.
|
|
729
|
+
const clusteredSkin =
|
|
730
|
+
clusteredLighting &&
|
|
731
|
+
entry.source.materials.every((material) => {
|
|
732
|
+
const shaderId = material.materialShaderId;
|
|
733
|
+
return (
|
|
734
|
+
!isStandardPbrSkinMaterialShader(shaderId) ||
|
|
735
|
+
isCanonicalStandardPbrMaterialShader(shaderId)
|
|
736
|
+
);
|
|
737
|
+
});
|
|
538
738
|
const skinMeshBindGroupLayout = clusteredSkin
|
|
539
739
|
? pipelineState.hdrpSkinMeshBindGroupLayout
|
|
540
740
|
: pipelineState.pbrSkinMeshBindGroupLayout;
|
|
@@ -567,6 +767,7 @@ export function recordGeometryDraws(
|
|
|
567
767
|
c.standardLighting,
|
|
568
768
|
runtime.device.caps.storageBuffer,
|
|
569
769
|
entry.mesh.layoutProjection.attributes.some((attribute) => attribute.key === 'color'),
|
|
770
|
+
probeBlendRecordAvailable,
|
|
570
771
|
),
|
|
571
772
|
);
|
|
572
773
|
if (!skinVariantSetResult.ok) runtime.errorRegistry.fire(skinVariantSetResult.error);
|
|
@@ -588,6 +789,9 @@ export function recordGeometryDraws(
|
|
|
588
789
|
undefined,
|
|
589
790
|
undefined,
|
|
590
791
|
entry.mesh.layoutProjection,
|
|
792
|
+
undefined,
|
|
793
|
+
undefined,
|
|
794
|
+
undefined,
|
|
591
795
|
) ?? null)
|
|
592
796
|
: null;
|
|
593
797
|
if (skinResources !== null && skinPsoProbe !== null) {
|
|
@@ -677,6 +881,19 @@ export function recordGeometryDraws(
|
|
|
677
881
|
// the async PSO compile resolves the cache hits and the next frame
|
|
678
882
|
// routes the skin BG + skin pipeline together. Mirrors the uniform
|
|
679
883
|
// null skip-draw shape (M6-T1, charter P3 explicit failure).
|
|
884
|
+
if (diagnosticsEnabled) {
|
|
885
|
+
console.error(
|
|
886
|
+
`[render-material] skin draw skipped: ${JSON.stringify({
|
|
887
|
+
entityKey: entry.source.entityKey,
|
|
888
|
+
materialHandle: entry.source.material.materialHandle,
|
|
889
|
+
reason: 'skin-pipeline-unavailable',
|
|
890
|
+
skinResourcesReady: skinResources !== null,
|
|
891
|
+
skinPsoReady: skinPsoProbe !== null,
|
|
892
|
+
paletteBufferReady: skinSlice?.buffer !== undefined,
|
|
893
|
+
paletteByteOffset: skinSlice?.byteOffset,
|
|
894
|
+
})}`,
|
|
895
|
+
);
|
|
896
|
+
}
|
|
680
897
|
continue;
|
|
681
898
|
}
|
|
682
899
|
// feat-20260520-2d-sprite-layer-mvp M-3 / w25 (@fallback sprite
|
|
@@ -771,6 +988,26 @@ export function recordGeometryDraws(
|
|
|
771
988
|
// injection, and Skylight merge; deduped cross-entity via the
|
|
772
989
|
// shaderId-outer `materialBgShared` cache.
|
|
773
990
|
const materialSlot = materialSlotIndices[i]?.[matSlotIdx] ?? materialSlotIndices[i]?.[0] ?? 0;
|
|
991
|
+
const processValue = (
|
|
992
|
+
globalThis as {
|
|
993
|
+
process?: { env?: Record<string, string | undefined> };
|
|
994
|
+
}
|
|
995
|
+
).process;
|
|
996
|
+
if (
|
|
997
|
+
processValue?.env?.FORGEAX_MATERIAL_PIPELINE_DIAGNOSTICS === '1' &&
|
|
998
|
+
(submeshMaterial.materialShaderId === 'forgeax::default-standard-pbr' ||
|
|
999
|
+
submeshMaterial.materialShaderId === 'forgeax::pbr-skin')
|
|
1000
|
+
) {
|
|
1001
|
+
console.error(
|
|
1002
|
+
`[render-material] draw receipt: ${JSON.stringify({
|
|
1003
|
+
entityIndex: entry.renderableIndex,
|
|
1004
|
+
materialSlot,
|
|
1005
|
+
materialHandle: submeshMaterial.materialHandle,
|
|
1006
|
+
clearcoat: submeshMaterial.paramSnapshot?.clearcoat,
|
|
1007
|
+
shader: submeshMaterial.materialShaderId,
|
|
1008
|
+
})}`,
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
774
1011
|
perSubmeshBg =
|
|
775
1012
|
profilePhase === undefined
|
|
776
1013
|
? resolveMaterialBindGroup(
|
|
@@ -792,8 +1029,12 @@ export function recordGeometryDraws(
|
|
|
792
1029
|
const smTopology = sm.topology;
|
|
793
1030
|
const smMaterialShaderId =
|
|
794
1031
|
entry.source.skin !== undefined
|
|
795
|
-
?
|
|
1032
|
+
? isStandardPbrSkinMaterialShader(submeshMaterial.materialShaderId)
|
|
1033
|
+
? submeshMaterial.materialShaderId
|
|
1034
|
+
: SKIN_MATERIAL_SHADER_ID
|
|
796
1035
|
: submeshMaterial.materialShaderId;
|
|
1036
|
+
const probeBlendAvailable =
|
|
1037
|
+
probeBlendRecordAvailable && isStandardPbrMaterialShader(smMaterialShaderId);
|
|
797
1038
|
const isSpriteShader =
|
|
798
1039
|
smMaterialShaderId === 'forgeax::sprite' || smMaterialShaderId === 'forgeax::sprite-lit';
|
|
799
1040
|
// Preserve the dedicated sprite-pass state when the linear-LDR graph
|
|
@@ -869,7 +1110,13 @@ export function recordGeometryDraws(
|
|
|
869
1110
|
c.standardLighting,
|
|
870
1111
|
runtime.device.caps.storageBuffer,
|
|
871
1112
|
hasVertexColor,
|
|
1113
|
+
probeBlendAvailable,
|
|
872
1114
|
);
|
|
1115
|
+
const transmissionAvailable = requestsStandardTransmissionVariant(submeshMaterial);
|
|
1116
|
+
const materialCapabilityVariantSet =
|
|
1117
|
+
transmissionAvailable && !capabilityVariantSet.includes('TRANSMISSION_AVAILABLE=')
|
|
1118
|
+
? `${capabilityVariantSet === '' ? '' : `${capabilityVariantSet}+`}TRANSMISSION_AVAILABLE=true`
|
|
1119
|
+
: capabilityVariantSet;
|
|
873
1120
|
// Sprite's base request must retain the boot-selected artifact. Only
|
|
874
1121
|
// SpriteInstances uses the explicit empty key for the
|
|
875
1122
|
// PER_INSTANCE_REGION=true variant; synthesizing the generic PBR
|
|
@@ -880,23 +1127,16 @@ export function recordGeometryDraws(
|
|
|
880
1127
|
? ''
|
|
881
1128
|
: undefined
|
|
882
1129
|
: entry.variantSet === undefined
|
|
883
|
-
?
|
|
1130
|
+
? materialCapabilityVariantSet
|
|
884
1131
|
: capabilityVariantSet === ''
|
|
885
1132
|
? entry.variantSet
|
|
886
1133
|
: `${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
1134
|
const cachedPipeline = resolveMaterialPipeline(
|
|
895
1135
|
smMaterialShaderId,
|
|
896
1136
|
pipelineRenderState,
|
|
897
1137
|
smTopology,
|
|
898
1138
|
entry.mesh.indexFormat,
|
|
899
|
-
|
|
1139
|
+
variantSet,
|
|
900
1140
|
colorFormatOverride,
|
|
901
1141
|
entry.mesh.layoutProjection,
|
|
902
1142
|
);
|
|
@@ -920,8 +1160,30 @@ export function recordGeometryDraws(
|
|
|
920
1160
|
}
|
|
921
1161
|
|
|
922
1162
|
if (smPipelineHandle === null) {
|
|
1163
|
+
if (diagnosticsEnabled) {
|
|
1164
|
+
console.error(
|
|
1165
|
+
`[render-material] draw skipped: ${JSON.stringify({
|
|
1166
|
+
entityKey: entry.source.entityKey,
|
|
1167
|
+
materialHandle: submeshMaterial.materialHandle,
|
|
1168
|
+
shader: smMaterialShaderId,
|
|
1169
|
+
reason: 'pipeline-unavailable',
|
|
1170
|
+
})}`,
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
923
1173
|
continue;
|
|
924
1174
|
}
|
|
1175
|
+
// The probe record is an ABI extension of the built-in Standard PBR
|
|
1176
|
+
// shaders only. RenderScene may retain a record on every projected
|
|
1177
|
+
// renderable, but unlit/custom shaders still use the one-binding
|
|
1178
|
+
// instances BGL and must never receive the probe bind group. Resolve
|
|
1179
|
+
// this per submesh so mixed-material meshes cannot cross the layouts.
|
|
1180
|
+
const instanceDraws = resolveGeometryInstanceBuffer(
|
|
1181
|
+
c,
|
|
1182
|
+
entry,
|
|
1183
|
+
identityInstanceDraws,
|
|
1184
|
+
probeBlendAvailable,
|
|
1185
|
+
);
|
|
1186
|
+
if (instanceDraws === null) continue;
|
|
925
1187
|
// Standard clustered PBR variants declare the unified cluster/SSAO
|
|
926
1188
|
// group(2) layout. Unlit and other URP-layout materials must bind the
|
|
927
1189
|
// ordinary mesh group instead; choosing one group for the whole pass
|
|
@@ -938,21 +1200,35 @@ export function recordGeometryDraws(
|
|
|
938
1200
|
if (selectedGroup === null) continue;
|
|
939
1201
|
group2BindGroup = selectedGroup;
|
|
940
1202
|
}
|
|
1203
|
+
if (diagnosticsEnabled && submeshMaterial.textureHandles !== undefined) {
|
|
1204
|
+
console.error(
|
|
1205
|
+
`[render-material] draw submitted: ${JSON.stringify({
|
|
1206
|
+
entityKey: entry.source.entityKey,
|
|
1207
|
+
materialHandle: submeshMaterial.materialHandle,
|
|
1208
|
+
shader: smMaterialShaderId,
|
|
1209
|
+
textureHandles: [...submeshMaterial.textureHandles.entries()].map(
|
|
1210
|
+
([field, handle]) => ({
|
|
1211
|
+
field,
|
|
1212
|
+
handle,
|
|
1213
|
+
}),
|
|
1214
|
+
),
|
|
1215
|
+
skin: isSkinEntry
|
|
1216
|
+
? {
|
|
1217
|
+
resourcesReady: skinResources !== null,
|
|
1218
|
+
psoReady: skinPsoProbe !== null,
|
|
1219
|
+
paletteBufferReady: skinSlice?.buffer !== undefined,
|
|
1220
|
+
paletteByteOffset: skinSlice?.byteOffset,
|
|
1221
|
+
dynamicOffsets: [...group2DynamicOffsets],
|
|
1222
|
+
}
|
|
1223
|
+
: undefined,
|
|
1224
|
+
pipelineReady: true,
|
|
1225
|
+
})}`,
|
|
1226
|
+
);
|
|
1227
|
+
}
|
|
941
1228
|
pass.setBindGroup(2, group2BindGroup, group2DynamicOffsets);
|
|
942
1229
|
|
|
943
1230
|
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', () =>
|
|
1231
|
+
recordOcclusionCandidate(() =>
|
|
956
1232
|
submitSubmeshDraws(
|
|
957
1233
|
pass,
|
|
958
1234
|
bindingState,
|
|
@@ -964,6 +1240,24 @@ export function recordGeometryDraws(
|
|
|
964
1240
|
sm.indexOffset,
|
|
965
1241
|
),
|
|
966
1242
|
);
|
|
1243
|
+
} else {
|
|
1244
|
+
profileGeometrySegment(c, passKind, 'draw-submit', () =>
|
|
1245
|
+
recordOcclusionCandidate(() =>
|
|
1246
|
+
submitSubmeshDraws(
|
|
1247
|
+
pass,
|
|
1248
|
+
bindingState,
|
|
1249
|
+
smPipelineHandle,
|
|
1250
|
+
instanceDraws,
|
|
1251
|
+
entry.mesh.indexed,
|
|
1252
|
+
sm.indexCount,
|
|
1253
|
+
sm.vertexCount,
|
|
1254
|
+
sm.indexOffset,
|
|
1255
|
+
),
|
|
1256
|
+
),
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
if (diagnosticsEnabled && perSubmeshBg !== null) {
|
|
1260
|
+
recordIblPipelineBinding(c, submeshMaterial, smPipelineHandle, perSubmeshBg);
|
|
967
1261
|
}
|
|
968
1262
|
}
|
|
969
1263
|
}
|
|
@@ -978,10 +1272,35 @@ function resolveGeometryInstanceBuffer(
|
|
|
978
1272
|
c: _InternalRenderPipelineContext,
|
|
979
1273
|
entry: _InternalRenderPipelineContext['validatedOrdered'][number],
|
|
980
1274
|
identityInstanceDraws: readonly GeometryInstanceDraw[],
|
|
1275
|
+
useProbeBlend: boolean,
|
|
981
1276
|
): readonly GeometryInstanceDraw[] | null {
|
|
982
1277
|
const { runtime, pipelineState, frameState } = c;
|
|
983
1278
|
const inst = entry.source.instances;
|
|
984
|
-
|
|
1279
|
+
const probeBinding =
|
|
1280
|
+
!useProbeBlend ||
|
|
1281
|
+
!runtime.device.caps.storageBuffer ||
|
|
1282
|
+
entry.source.probeBlendRecord === undefined
|
|
1283
|
+
? undefined
|
|
1284
|
+
: resolveProbeBlendBuffer(
|
|
1285
|
+
c,
|
|
1286
|
+
entry.source.probeBlendRecord,
|
|
1287
|
+
worldEntityKey(entry.source.worldId, entry.source.entityKey),
|
|
1288
|
+
);
|
|
1289
|
+
if (inst === undefined) {
|
|
1290
|
+
const identity = identityInstanceDraws[0];
|
|
1291
|
+
if (identity === undefined) return null;
|
|
1292
|
+
return [
|
|
1293
|
+
{
|
|
1294
|
+
...identity,
|
|
1295
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(
|
|
1296
|
+
c,
|
|
1297
|
+
pipelineState.identityInstanceBuffer,
|
|
1298
|
+
probeBinding?.buffer,
|
|
1299
|
+
),
|
|
1300
|
+
probeOffset: probeBinding?.offset ?? -1,
|
|
1301
|
+
},
|
|
1302
|
+
];
|
|
1303
|
+
}
|
|
985
1304
|
// A present, empty Instances array means zero draws. Do not fall back to
|
|
986
1305
|
// the shared identity buffer, which would silently render one instance.
|
|
987
1306
|
if (inst.instanceCount === 0) return [];
|
|
@@ -1022,7 +1341,12 @@ function resolveGeometryInstanceBuffer(
|
|
|
1022
1341
|
}
|
|
1023
1342
|
draws.push({
|
|
1024
1343
|
instanceBuffer: buffer.handle,
|
|
1025
|
-
instanceBindGroup: resolveGeometryInstancesBindGroup(
|
|
1344
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(
|
|
1345
|
+
c,
|
|
1346
|
+
buffer.handle,
|
|
1347
|
+
probeBinding?.buffer,
|
|
1348
|
+
),
|
|
1349
|
+
probeOffset: probeBinding?.offset ?? -1,
|
|
1026
1350
|
instanceCount: count,
|
|
1027
1351
|
});
|
|
1028
1352
|
}
|
|
@@ -1114,25 +1438,80 @@ function resolveGeometryInstanceBuffer(
|
|
|
1114
1438
|
return [
|
|
1115
1439
|
{
|
|
1116
1440
|
instanceBuffer,
|
|
1117
|
-
instanceBindGroup: resolveGeometryInstancesBindGroup(c, instanceBuffer),
|
|
1441
|
+
instanceBindGroup: resolveGeometryInstancesBindGroup(c, instanceBuffer, probeBinding?.buffer),
|
|
1442
|
+
probeOffset: probeBinding?.offset ?? -1,
|
|
1118
1443
|
instanceCount,
|
|
1119
1444
|
},
|
|
1120
1445
|
];
|
|
1121
1446
|
}
|
|
1122
1447
|
|
|
1123
|
-
function
|
|
1448
|
+
export function resolveProbeBlendBuffer(
|
|
1449
|
+
c: _InternalRenderPipelineContext,
|
|
1450
|
+
record: import('../scene/probe-blend-record').ProbeBlendRecord | undefined,
|
|
1451
|
+
entityKey?: number,
|
|
1452
|
+
): { readonly buffer: Buffer; readonly offset: number } {
|
|
1453
|
+
const { runtime, frameState } = c;
|
|
1454
|
+
const usage = runtime.device.caps.storageBuffer
|
|
1455
|
+
? GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST
|
|
1456
|
+
: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
|
|
1457
|
+
if (record === undefined) throw new Error('probe blend record is required for probe allocation');
|
|
1458
|
+
if (entityKey === undefined) throw new Error('probe blend record requires an entity key');
|
|
1459
|
+
const offset = probeBlendRecordOffset(record.objectKey);
|
|
1460
|
+
const requiredCapacity = record.objectKey + 2;
|
|
1461
|
+
let buffer = frameState.probeBlendRecordBuffer;
|
|
1462
|
+
if (buffer === undefined || frameState.probeBlendRecordBufferCapacity < requiredCapacity) {
|
|
1463
|
+
const created = runtime.device.createBuffer({
|
|
1464
|
+
label: 'probe-blend-records',
|
|
1465
|
+
size: requiredCapacity * PROBE_BLEND_RECORD_STRIDE,
|
|
1466
|
+
usage,
|
|
1467
|
+
mappedAtCreation: false,
|
|
1468
|
+
});
|
|
1469
|
+
if (!created.ok) throw created.error;
|
|
1470
|
+
buffer = new GpuBuffer(runtime.device, created.value);
|
|
1471
|
+
frameState.probeBlendRecordBuffer = buffer;
|
|
1472
|
+
frameState.probeBlendRecordBufferCapacity = requiredCapacity;
|
|
1473
|
+
// The cache is tied to the previous backing allocation. A new buffer has
|
|
1474
|
+
// no valid record contents, so every later object must upload its full
|
|
1475
|
+
// 160B payload even when generation/bytes match the old allocation.
|
|
1476
|
+
frameState.probeBlendBuffers.clear();
|
|
1477
|
+
}
|
|
1478
|
+
const cached = frameState.probeBlendBuffers.get(entityKey);
|
|
1479
|
+
const unchanged =
|
|
1480
|
+
cached !== undefined &&
|
|
1481
|
+
cached.generation === record.generation &&
|
|
1482
|
+
cached.bytes.length === record.bytes.length &&
|
|
1483
|
+
cached.bytes.every((value, index) => value === record.bytes[index]);
|
|
1484
|
+
if (!unchanged) {
|
|
1485
|
+
const uploaded = runtime.device.queue.writeBuffer(buffer.handle, offset, record.bytes);
|
|
1486
|
+
if (!uploaded.ok) throw uploaded.error;
|
|
1487
|
+
// Publish the generation only after the complete 160B queue write succeeds.
|
|
1488
|
+
frameState.probeBlendBuffers.set(entityKey, {
|
|
1489
|
+
generation: record.generation,
|
|
1490
|
+
bytes: new Uint8Array(record.bytes),
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
return { buffer: buffer.handle, offset };
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
export function resolveGeometryInstancesBindGroup(
|
|
1124
1497
|
c: _InternalRenderPipelineContext,
|
|
1125
1498
|
instanceBuffer: Buffer,
|
|
1499
|
+
probeBuffer?: Buffer,
|
|
1126
1500
|
): BindGroup {
|
|
1127
1501
|
const { runtime, pipelineState, frameState, bindGroupCounts } = c;
|
|
1502
|
+
const layout =
|
|
1503
|
+
probeBuffer === undefined
|
|
1504
|
+
? pipelineState.instancesBindGroupLayout
|
|
1505
|
+
: pipelineState.probeInstancesBindGroupLayout;
|
|
1506
|
+
if (layout === undefined) throw new Error('probe instances bind-group layout is unavailable');
|
|
1128
1507
|
return getOrCreateFromChain(
|
|
1129
1508
|
frameState.instancesBgShared,
|
|
1130
|
-
[
|
|
1131
|
-
'instances',
|
|
1509
|
+
probeBuffer === undefined ? [layout, instanceBuffer] : [layout, instanceBuffer, probeBuffer],
|
|
1510
|
+
probeBuffer === undefined ? 'instances-no-probe' : 'instances-probe',
|
|
1132
1511
|
() => {
|
|
1133
1512
|
const result = runtime.device.createBindGroup({
|
|
1134
1513
|
label: 'pbr-instances-bg',
|
|
1135
|
-
layout
|
|
1514
|
+
layout,
|
|
1136
1515
|
entries: [
|
|
1137
1516
|
{
|
|
1138
1517
|
binding: 0,
|
|
@@ -1141,6 +1520,17 @@ function resolveGeometryInstancesBindGroup(
|
|
|
1141
1520
|
value: { buffer: instanceBuffer },
|
|
1142
1521
|
},
|
|
1143
1522
|
},
|
|
1523
|
+
...(probeBuffer === undefined
|
|
1524
|
+
? []
|
|
1525
|
+
: [
|
|
1526
|
+
{
|
|
1527
|
+
binding: 1,
|
|
1528
|
+
resource: {
|
|
1529
|
+
kind: 'buffer' as const,
|
|
1530
|
+
value: { buffer: probeBuffer, offset: 0, size: PROBE_BLEND_RECORD_BYTE_SIZE },
|
|
1531
|
+
},
|
|
1532
|
+
},
|
|
1533
|
+
]),
|
|
1144
1534
|
],
|
|
1145
1535
|
});
|
|
1146
1536
|
if (!result.ok) throw result.error;
|