@forgeax/engine-render 0.1.19 → 0.1.21
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 +215 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/assembly/device-feature-admission.d.ts +18 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -0
- package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
- package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +34 -20
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +9 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/render-target-host.d.ts +46 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -0
- package/dist/assets/render-asset-port.d.ts.map +1 -1
- package/dist/authoring.mjs +3 -0
- package/dist/authoring.mjs.map +1 -1
- package/dist/capture/cube-views.d.ts +21 -0
- package/dist/capture/cube-views.d.ts.map +1 -0
- package/dist/capture/scheduler.d.ts +54 -0
- package/dist/capture/scheduler.d.ts.map +1 -0
- package/dist/{chunk-RJRUS55L.mjs → chunk-5YADUCA7.mjs} +1896 -1624
- package/dist/chunk-5YADUCA7.mjs.map +1 -0
- package/dist/{chunk-LOSO4CTV.mjs → chunk-6OPXDQ2E.mjs} +423 -46
- package/dist/chunk-6OPXDQ2E.mjs.map +1 -0
- package/dist/{chunk-IPXCABEP.mjs → chunk-BXBQQKFQ.mjs} +3 -9
- package/dist/chunk-BXBQQKFQ.mjs.map +1 -0
- package/dist/chunk-FS2KNUQH.mjs +1294 -0
- package/dist/chunk-FS2KNUQH.mjs.map +1 -0
- package/dist/components/camera.d.ts +1 -0
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/cube-camera.d.ts +20 -0
- package/dist/components/cube-camera.d.ts.map +1 -0
- package/dist/components/directional-light.d.ts +11 -2
- package/dist/components/directional-light.d.ts.map +1 -1
- package/dist/components/directional-shadow-filter.d.ts +25 -0
- package/dist/components/directional-shadow-filter.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/reflection-probe.d.ts +17 -0
- package/dist/components/reflection-probe.d.ts.map +1 -0
- package/dist/components/spot-light.d.ts +12 -0
- package/dist/components/spot-light.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +8552 -1612
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +19 -2
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +5 -0
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/render.d.ts +209 -93
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/directional-shadow-projection.d.ts +23 -0
- package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
- package/dist/extract/environment.d.ts +14 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/extract/visibility.d.ts.map +1 -1
- package/dist/features/fullscreen.d.ts.map +1 -1
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +10 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +13 -2
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +0 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-usage.d.ts +2 -0
- package/dist/gpu-usage.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +19 -17
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +4 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/kernel-cache.d.ts +36 -0
- package/dist/ibl/kernel-cache.d.ts.map +1 -0
- package/dist/index.d.ts +35 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +51 -0
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances-derived-bounds.d.ts +50 -0
- package/dist/instances-derived-bounds.d.ts.map +1 -0
- package/dist/internal.mjs +1 -1
- package/dist/light-buffer-layout.d.ts +30 -13
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +54 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +20 -7
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts +2 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
- package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
- package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
- package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
- package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
- package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
- package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts +4 -13
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline/standard-profile.d.ts +12 -20
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +40 -7
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/point-shadow-inspection.d.ts +21 -0
- package/dist/point-shadow-inspection.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +29 -32
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +65 -15
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts +5 -0
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +12 -5
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
- package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
- package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/index.d.ts +8 -0
- package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
- package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/session.d.ts +43 -0
- package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +37 -0
- package/dist/record/gpu-timing.d.ts.map +1 -0
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +23 -2
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +48 -3
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +81 -5
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +7 -4
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/reflection/filter.d.ts +22 -0
- package/dist/reflection/filter.d.ts.map +1 -0
- package/dist/reflection/gpu-table.d.ts +25 -0
- package/dist/reflection/gpu-table.d.ts.map +1 -0
- package/dist/reflection/projection.d.ts +91 -0
- package/dist/reflection/projection.d.ts.map +1 -0
- package/dist/render-contract.d.ts +114 -7
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-data.d.ts +10 -6
- package/dist/render-data.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +1 -0
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +78 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +113 -20
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +24 -3
- package/dist/render-system.d.ts.map +1 -1
- package/dist/renderer-inspect.d.ts +29 -0
- package/dist/renderer-inspect.d.ts.map +1 -0
- package/dist/renderer.d.ts +43 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/scene/render-scene.d.ts +14 -0
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/shadow-atlas.d.ts +3 -3
- package/dist/shadow-atlas.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +3 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/targets/contracts.d.ts +66 -0
- package/dist/targets/contracts.d.ts.map +1 -0
- package/dist/targets/graph-projection.d.ts +29 -0
- package/dist/targets/graph-projection.d.ts.map +1 -0
- package/dist/targets/material-source.d.ts +34 -0
- package/dist/targets/material-source.d.ts.map +1 -0
- package/dist/targets/owner.d.ts +32 -0
- package/dist/targets/owner.d.ts.map +1 -0
- package/dist/targets/physical.d.ts +18 -0
- package/dist/targets/physical.d.ts.map +1 -0
- package/dist/targets/readback.d.ts +39 -0
- package/dist/targets/readback.d.ts.map +1 -0
- package/dist/temporal/frame.d.ts +44 -0
- package/dist/temporal/frame.d.ts.map +1 -0
- package/dist/temporal/index.mjs +3 -3
- package/dist/typed-render-graph-primitives.d.ts +6 -1
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-atlas.d.ts +10 -0
- package/dist/typed-shadow-atlas.d.ts.map +1 -0
- package/dist/typed-shadow-passes.d.ts +1 -1
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/capability.d.ts +57 -0
- package/dist/volume/capability.d.ts.map +1 -0
- package/dist/volume/component.d.ts +61 -0
- package/dist/volume/component.d.ts.map +1 -0
- package/dist/volume/extract.d.ts +11 -0
- package/dist/volume/extract.d.ts.map +1 -0
- package/dist/volume/inspection.d.ts +38 -0
- package/dist/volume/inspection.d.ts.map +1 -0
- package/dist/volume/passes.d.ts +38 -0
- package/dist/volume/passes.d.ts.map +1 -0
- package/dist/volume/recovery.d.ts +38 -0
- package/dist/volume/recovery.d.ts.map +1 -0
- package/dist/volume/resources.d.ts +57 -0
- package/dist/volume/resources.d.ts.map +1 -0
- package/dist/volume/temporal.d.ts +35 -0
- package/dist/volume/temporal.d.ts.map +1 -0
- package/package.json +20 -20
- package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
- package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
- package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
- package/src/__tests__/cluster-binner.unit.test.ts +35 -0
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -2
- package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
- package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
- package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
- package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
- package/src/__tests__/cube-camera.integration.test.ts +42 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +73 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -3
- package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
- package/src/__tests__/factory-contract.integration.test.ts +255 -29
- package/src/__tests__/fog-component.unit.test.ts +67 -0
- package/src/__tests__/fog.integration.test.ts +86 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -9
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +17 -1
- package/src/__tests__/gpu-driven-production.integration.test.ts +16 -17
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +12 -4
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
- package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
- package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
- package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
- package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
- package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
- package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
- package/src/__tests__/instances-culling.integration.test.ts +94 -0
- package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -14
- package/src/__tests__/material-observation.integration.test.ts +101 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
- package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
- package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
- package/src/__tests__/public-surface.test-d.ts +10 -0
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
- package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
- package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
- package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
- package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
- package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +23 -3
- package/src/__tests__/render-feature-docs.unit.test.ts +1 -1
- package/src/__tests__/render-target-admission.unit.test.ts +80 -0
- package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
- package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
- package/src/__tests__/render-target-material-source.test-d.ts +30 -0
- package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
- package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
- package/src/__tests__/render-target-owner.unit.test.ts +122 -0
- package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
- package/src/__tests__/render-target-public-schema.json +107 -0
- package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
- package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
- package/src/__tests__/render-target-readback.integration.test.ts +90 -0
- package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +76 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +1 -1
- package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
- package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
- package/src/__tests__/skin-motion-regression.unit.test.ts +132 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +32 -2
- package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
- package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +232 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +8 -5
- package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
- package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
- package/src/__tests__/standard-lighting-write.unit.test.ts +377 -0
- package/src/__tests__/standard-lighting.integration.test.ts +67 -0
- package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
- package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
- package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
- package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -36
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
- package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
- package/src/__tests__/volume-optics-oracle.unit.test.ts +85 -0
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +655 -0
- package/src/__tests__/volumetric-fog-component.unit.test.ts +71 -0
- package/src/__tests__/volumetric-fog-composite-stage-readback.dawn.test.ts +376 -0
- package/src/__tests__/volumetric-fog-errors.unit.test.ts +51 -0
- package/src/__tests__/volumetric-fog-inspection.unit.test.ts +77 -0
- package/src/__tests__/volumetric-fog-light-capability.unit.test.ts +19 -0
- package/src/__tests__/volumetric-fog-light-consumers.integration.test.ts +18 -0
- package/src/__tests__/volumetric-fog-light-errors.unit.test.ts +17 -0
- package/src/__tests__/volumetric-fog-light-topology.unit.test.ts +21 -0
- package/src/__tests__/volumetric-fog-light-transaction.integration.test.ts +53 -0
- package/src/__tests__/volumetric-fog-m9-watcher.integration.test.ts +27 -0
- package/src/__tests__/volumetric-fog-point-light-owner.integration.test.ts +44 -0
- package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +49 -0
- package/src/__tests__/volumetric-fog-point-spot-contract.unit.test.ts +28 -0
- package/src/__tests__/volumetric-fog-point-spot-lkg.integration.test.ts +65 -0
- package/src/__tests__/volumetric-fog-point-spot-selection.integration.test.ts +49 -0
- package/src/__tests__/volumetric-fog-point-spot-temporal.unit.test.ts +55 -0
- package/src/__tests__/volumetric-fog-projector-contract.unit.test.ts +22 -0
- package/src/__tests__/volumetric-fog-projector-inspection.unit.test.ts +12 -0
- package/src/__tests__/volumetric-fog-projector-surface-volume.integration.test.ts +11 -0
- package/src/__tests__/volumetric-fog-projector-transaction.integration.test.ts +26 -0
- package/src/__tests__/volumetric-fog-recovery.integration.test.ts +47 -0
- package/src/__tests__/volumetric-fog-selected-light-resolution.integration.test.ts +63 -0
- package/src/__tests__/volumetric-fog-spot-closure.integration.test.ts +26 -0
- package/src/__tests__/volumetric-fog-spot-contract.test-d.ts +21 -0
- package/src/__tests__/volumetric-fog-spot-contract.unit.test.ts +27 -0
- package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +14 -0
- package/src/__tests__/volumetric-fog-spot-optics.integration.test.ts +29 -0
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +550 -0
- package/src/__tests__/volumetric-fog-temporal-selected-light.unit.test.ts +33 -0
- package/src/__tests__/volumetric-fog-temporal.unit.test.ts +45 -0
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +237 -0
- package/src/__tests__/volumetric-fog-transparent.integration.test.ts +27 -0
- package/src/assembly/device-feature-admission.ts +73 -0
- package/src/assembly/directional-shadow-inspection.ts +122 -0
- package/src/assembly/factory.ts +1093 -246
- package/src/assembly/host-contract.ts +25 -0
- package/src/assembly/render-target-host.ts +847 -0
- package/src/assets/asset-decoders.ts +1 -1
- package/src/assets/render-asset-port.ts +7 -1
- package/src/capture/cube-views.ts +69 -0
- package/src/capture/scheduler.ts +265 -0
- package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
- package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
- package/src/components/camera.ts +4 -0
- package/src/components/cube-camera.ts +52 -0
- package/src/components/directional-light.ts +22 -2
- package/src/components/directional-shadow-filter.ts +57 -0
- package/src/components/index.ts +2 -0
- package/src/components/light-helpers.ts +85 -7
- package/src/components/reflection-probe.ts +49 -0
- package/src/components/spot-light.ts +22 -3
- package/src/device/gpu-residency.ts +168 -58
- package/src/environment/frame.ts +6 -24
- package/src/environment/lifecycle.ts +12 -0
- package/src/errors/render.ts +405 -143
- package/src/extract/directional-shadow-projection.ts +61 -0
- package/src/extract/environment.ts +57 -0
- package/src/extract/visibility.ts +25 -1
- package/src/features/fullscreen.ts +3 -0
- package/src/features/targets.ts +4 -1
- package/src/features/types.ts +10 -0
- package/src/fullscreen-post-process-pass.ts +43 -2
- package/src/gpu-driven/batch-topology.ts +1 -0
- package/src/gpu-driven/production-raster.ts +1 -3
- package/src/gpu-scene.ts +8 -1
- package/src/gpu-usage.ts +2 -0
- package/src/hdrp-buffers.ts +165 -59
- package/src/ibl/IblPipelineCache.ts +11 -0
- package/src/ibl/kernel-cache.ts +88 -0
- package/src/index.ts +186 -1
- package/src/inspection-types.ts +56 -0
- package/src/instances-derived-bounds.ts +171 -0
- package/src/light-buffer-layout.ts +74 -26
- package/src/mesh-material-bindings.ts +132 -0
- package/src/pbr-pipeline.ts +139 -27
- package/src/pipeline/standard-forward-lane.ts +65 -15
- package/src/pipeline/standard-lighting/errors.ts +6 -0
- package/src/pipeline/standard-lighting/graph.ts +157 -0
- package/src/pipeline/standard-lighting/inspection.ts +88 -0
- package/src/pipeline/standard-lighting/layout.ts +31 -0
- package/src/pipeline/standard-lighting/light-frame.ts +34 -0
- package/src/pipeline/standard-lighting/membership.ts +43 -0
- package/src/pipeline/standard-lighting/prepare.ts +37 -0
- package/src/pipeline/standard-lighting/topology.ts +120 -0
- package/src/pipeline/standard-lighting/transport.ts +77 -0
- package/src/pipeline/standard-pipeline.ts +141 -192
- package/src/pipeline/standard-post.ts +26 -7
- package/src/pipeline/standard-profile.ts +23 -30
- package/src/pipeline-spec.ts +84 -21
- package/src/point-shadow-inspection.ts +55 -0
- package/src/record/__tests__/temporal-payload.unit.test.ts +42 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
- package/src/record/frame-lighting.ts +470 -516
- package/src/record/frame-snapshot.ts +76 -28
- package/src/record/frame-targets.ts +23 -2
- package/src/record/frame.ts +1169 -79
- package/src/record/gpu-pass-timing/contract.ts +180 -0
- package/src/record/gpu-pass-timing/errors.ts +34 -0
- package/src/record/gpu-pass-timing/index.ts +37 -0
- package/src/record/gpu-pass-timing/parser.ts +97 -0
- package/src/record/gpu-pass-timing/session.ts +938 -0
- package/src/record/gpu-timing.ts +233 -0
- package/src/record/main-pass-geometry.ts +120 -80
- package/src/record/main-pass-material.ts +101 -11
- package/src/record/main-pass-sprite-draws.ts +54 -25
- package/src/record/main-pass.ts +71 -15
- package/src/record/render-context.ts +77 -0
- package/src/record/shadow-pass.ts +104 -66
- package/src/record/skybox-post-pass.ts +20 -4
- package/src/record/typed-frame-graph.ts +1016 -32
- package/src/record/view-ubo.ts +63 -28
- package/src/reflection/filter.ts +81 -0
- package/src/reflection/gpu-table.ts +44 -0
- package/src/reflection/projection.ts +281 -0
- package/src/render-contract.ts +147 -4
- package/src/render-data.ts +50 -22
- package/src/render-graph-primitives.ts +9 -4
- package/src/render-pipeline.ts +161 -2
- package/src/render-system-extract.ts +886 -103
- package/src/render-system.ts +1174 -66
- package/src/renderer-inspect.ts +66 -0
- package/src/renderer.ts +222 -0
- package/src/scene/render-scene.ts +117 -9
- package/src/shadow-atlas.ts +5 -5
- package/src/ssao-buffers.ts +9 -2
- package/src/targets/contracts.ts +182 -0
- package/src/targets/graph-projection.ts +169 -0
- package/src/targets/material-source.ts +143 -0
- package/src/targets/owner.ts +214 -0
- package/src/targets/physical.ts +18 -0
- package/src/targets/readback.ts +153 -0
- package/src/temporal/frame.ts +128 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +61 -23
- package/src/typed-render-graph-primitives.ts +34 -2
- package/src/typed-shadow-atlas.ts +17 -0
- package/src/typed-shadow-passes.ts +47 -40
- package/src/volume/capability.ts +173 -0
- package/src/volume/component.ts +110 -0
- package/src/volume/extract.ts +21 -0
- package/src/volume/inspection.ts +78 -0
- package/src/volume/passes.ts +686 -0
- package/src/volume/recovery.ts +86 -0
- package/src/volume/resources.ts +236 -0
- package/src/volume/temporal.ts +89 -0
- package/dist/chunk-IPXCABEP.mjs.map +0 -1
- package/dist/chunk-LOSO4CTV.mjs.map +0 -1
- package/dist/chunk-RJRUS55L.mjs.map +0 -1
- package/dist/chunk-YTQ5C7YQ.mjs +0 -584
- package/dist/chunk-YTQ5C7YQ.mjs.map +0 -1
|
@@ -15,23 +15,24 @@
|
|
|
15
15
|
// PointLight in common.wgsl. -1 (0xFFFFFFFF) is the no-shadow
|
|
16
16
|
// sentinel — shader path samples shadow only when layer >= 0.
|
|
17
17
|
//
|
|
18
|
-
// SpotLight (
|
|
18
|
+
// SpotLight (80 B / 20 floats):
|
|
19
19
|
// [ 0..2 ] position vec3<f32>
|
|
20
20
|
// [ 3 ] invRangeSquared f32
|
|
21
21
|
// [ 4..6 ] color vec3<f32> (host-pre-multiplied)
|
|
22
22
|
// [ 7 ] cosInner f32
|
|
23
23
|
// [ 8..10] direction vec3<f32> (raw outgoing vector)
|
|
24
24
|
// [ 11 ] cosOuter f32
|
|
25
|
-
// [12
|
|
25
|
+
// [12] depthBias, [13] normalBias, [14] pcfKernelSize
|
|
26
26
|
// [ 15 ] shadowAtlasTile i32 (sentinel -1 = unassigned/clipped; 0..3 = tile)
|
|
27
27
|
// — feat-20260625-spot-light-shadow-mapping M2 / w8 (D-4):
|
|
28
|
-
// SpotLight
|
|
29
|
-
//
|
|
30
|
-
// written i32 via an Int32Array view of the same backing
|
|
28
|
+
// SpotLight receiver controls occupy the 4th vec4 column. The tile
|
|
29
|
+
// lane is written i32 via an Int32Array view of the same backing
|
|
31
30
|
// ArrayBuffer; the shader reads `shadowAtlasTile: i32` from byte
|
|
32
31
|
// 60..64 of struct SpotLight (common.wgsl). -1 (0xFFFFFFFF) is the
|
|
33
32
|
// unassigned/clipped sentinel — shader samples shadow only when
|
|
34
33
|
// tile >= 0. Mirrors point's slot-7 shadowAtlasLayer pattern.
|
|
34
|
+
// [ 16 ] shadowIntensity f32 (default 1; [0,1] residual visibility)
|
|
35
|
+
// [17..19] std430 tail pad (the struct rounds to the next 16 B boundary)
|
|
35
36
|
//
|
|
36
37
|
// Array header (16 B, std430 stride alignment):
|
|
37
38
|
// [ 0 ] count u32 (number of valid slots in the trailing array)
|
|
@@ -69,13 +70,16 @@ import type { PointLightSnapshot, SpotLightSnapshot } from './render-system-extr
|
|
|
69
70
|
// [ 11 ] cosOuter f32 (point: 0.0)
|
|
70
71
|
// [ 12 ] kind u32 (POINT = 0, SPOT = 1)
|
|
71
72
|
// [ 13 ] shadow identity i32 (point layer / spot tile, -1 sentinel)
|
|
72
|
-
// [14
|
|
73
|
+
// [14] point near / spot shadowIntensity f32
|
|
74
|
+
// [15] point far / spot pcfKernelSize f32
|
|
73
75
|
//
|
|
74
76
|
// Design: research Finding 1 (Bevy GpuClusteredLight 152B -> forgeax 64B),
|
|
75
77
|
// plan-strategy D-light-slot (kind bit-tag discriminant).
|
|
76
78
|
//
|
|
77
|
-
// The existing URP PointLight (32B)
|
|
78
|
-
//
|
|
79
|
+
// The existing URP PointLight (32B) pack function remains unchanged; the URP
|
|
80
|
+
// SpotLight grows from 64B to 80B to carry the independent shadow visibility
|
|
81
|
+
// factor without stealing the tile or PCF lanes. packLightSlot remains the
|
|
82
|
+
// compact 64B HDRP owner and uses a spot-only pad lane for the same value.
|
|
79
83
|
|
|
80
84
|
/** Byte size of one HDRP LightSlot in std430 (16 x f32). AC-11 absolute-value lock. */
|
|
81
85
|
export const BYTES_PER_LIGHT_SLOT = 64;
|
|
@@ -99,9 +103,11 @@ export type LightSlotKind = (typeof LightSlotKind)[keyof typeof LightSlotKind];
|
|
|
99
103
|
* feat-20260612-point-light-shadows-urp-hdrp M4 / T-M4-4 (plan-strategy §D-8):
|
|
100
104
|
* the prior u32x3 pad lanes at byte 52..64 carry shadow-side data on the HDRP
|
|
101
105
|
* path. `kind_and_pad.x = kind` (u32), `.y = shadow identity` (i32, sentinel
|
|
102
|
-
* -1 = no shadow)
|
|
103
|
-
*
|
|
104
|
-
*
|
|
106
|
+
* -1 = no shadow). For point lights `.z/.w` carry near/far (f32 via bitcast);
|
|
107
|
+
* for spot lights `.z` carries shadowIntensity and `.w` carries the PCF
|
|
108
|
+
* kernel width (f32 via bitcast). The shader reads these lanes through
|
|
109
|
+
* `bitcast<f32>(...)` to
|
|
110
|
+
* keep the WGSL struct as `vec4<u32>` (alignment + naga_oil unchanged).
|
|
105
111
|
*/
|
|
106
112
|
export const LIGHTSLOT_LAYOUT = {
|
|
107
113
|
byteSize: BYTES_PER_LIGHT_SLOT,
|
|
@@ -117,6 +123,7 @@ export const LIGHTSLOT_LAYOUT = {
|
|
|
117
123
|
shadowAtlasTileOffset: 52,
|
|
118
124
|
shadowNearOffset: 56,
|
|
119
125
|
shadowFarOffset: 60,
|
|
126
|
+
spotPcfKernelSizeOffset: 60,
|
|
120
127
|
floatCount: 16,
|
|
121
128
|
vec4Count: 4,
|
|
122
129
|
} as const;
|
|
@@ -137,16 +144,27 @@ export const STORAGE_BUFFER_MIN_REQUIRED = 4;
|
|
|
137
144
|
/** Byte size of one PointLight std430 slot (vec4 * 2). */
|
|
138
145
|
export const POINT_LIGHT_STD430_BYTES = 32;
|
|
139
146
|
/**
|
|
140
|
-
* Byte size of one SpotLight std430 slot (
|
|
147
|
+
* Byte size of one SpotLight std430 slot (five 16-byte columns).
|
|
141
148
|
*
|
|
142
|
-
* feat-20260625-spot-light-shadow-mapping M2 / w8 (D-4)
|
|
143
|
-
*
|
|
144
|
-
*
|
|
149
|
+
* feat-20260625-spot-light-shadow-mapping M2 / w8 (D-4) grew 48 -> 64 for
|
|
150
|
+
* `shadowAtlasTile`; the visual-parity contract then adds a fifth column for
|
|
151
|
+
* `shadowIntensity` rather than overloading the tile/PCF lanes.
|
|
145
152
|
*/
|
|
146
|
-
export const SPOT_LIGHT_STD430_BYTES =
|
|
153
|
+
export const SPOT_LIGHT_STD430_BYTES = 80;
|
|
147
154
|
|
|
148
155
|
/** Sentinel value for SpotLight slot[15] meaning "no shadow / clipped". */
|
|
149
156
|
export const SPOT_LIGHT_SHADOW_TILE_SENTINEL = -1;
|
|
157
|
+
/** Sentinel for a projector-only SpotLight with no shadow atlas tile. */
|
|
158
|
+
export const SPOT_LIGHT_PROJECTOR_ONLY_SENTINEL = -2;
|
|
159
|
+
/**
|
|
160
|
+
* High-bit marker carried by the shared LightSlot identity lane when this
|
|
161
|
+
* SpotLight is the one projector selected for the frame. The lower 30 bits
|
|
162
|
+
* retain the shadow-atlas tile (0..3), or zero for projector-only lights, so
|
|
163
|
+
* one 64-byte slot carries both shadow and projector identity without growing
|
|
164
|
+
* the cluster UBO or inventing a second light list.
|
|
165
|
+
*/
|
|
166
|
+
export const SPOT_LIGHT_PROJECTOR_FLAG = 0x40000000;
|
|
167
|
+
export const SPOT_LIGHT_TILE_MASK = SPOT_LIGHT_PROJECTOR_FLAG - 1;
|
|
150
168
|
/** Byte size of the array header (count u32 + 12 B pad to 16 B stride). */
|
|
151
169
|
export const LIGHT_ARRAY_HEADER_BYTES = 16;
|
|
152
170
|
/** Maximum number of slots packed in the first-slice cap layout (D-S3). */
|
|
@@ -182,7 +200,7 @@ export function packPointLight(snap: PointLightSnapshot): Float32Array {
|
|
|
182
200
|
}
|
|
183
201
|
|
|
184
202
|
/**
|
|
185
|
-
* Pack one SpotLightSnapshot into
|
|
203
|
+
* Pack one SpotLightSnapshot into 20 floats (80 B byte-for-byte std430).
|
|
186
204
|
*
|
|
187
205
|
* cosInner / cosOuter ride the otherwise-padding `.w` lanes of the
|
|
188
206
|
* `color` and `direction` vec4 columns (AC-04 c + plan D-S2 16 B alignment
|
|
@@ -190,10 +208,13 @@ export function packPointLight(snap: PointLightSnapshot): Float32Array {
|
|
|
190
208
|
* (sentinel -1 = unassigned/clipped, 0..3 = atlas tile) written through an
|
|
191
209
|
* Int32Array view so the shader's `i32` read at byte 60..64 of struct SpotLight
|
|
192
210
|
* (common.wgsl) sees the correct two's-complement bits (-1 = 0xFFFFFFFF).
|
|
193
|
-
* Slots 12..14
|
|
211
|
+
* Slots 12..14 carry the shared receiver controls; slot 15 remains the i32
|
|
212
|
+
* shadow tile sentinel; slot 16 carries shadowIntensity and slots 17..19 are
|
|
213
|
+
* alignment tail padding. Surface and volume consumers therefore share one
|
|
214
|
+
* extracted shadow configuration.
|
|
194
215
|
*/
|
|
195
216
|
export function packSpotLight(snap: SpotLightSnapshot): Float32Array {
|
|
196
|
-
const out = new Float32Array(
|
|
217
|
+
const out = new Float32Array(20);
|
|
197
218
|
out[0] = snap.position[0] ?? 0;
|
|
198
219
|
out[1] = snap.position[1] ?? 0;
|
|
199
220
|
out[2] = snap.position[2] ?? 0;
|
|
@@ -206,10 +227,20 @@ export function packSpotLight(snap: SpotLightSnapshot): Float32Array {
|
|
|
206
227
|
out[9] = snap.direction[1] ?? 0;
|
|
207
228
|
out[10] = snap.direction[2] ?? 0;
|
|
208
229
|
out[11] = snap.cosOuter;
|
|
209
|
-
|
|
230
|
+
out[12] = snap.depthBias ?? 0.005;
|
|
231
|
+
out[13] = snap.normalBias ?? 0.05;
|
|
232
|
+
out[14] = snap.pcfKernelSize ?? 3;
|
|
210
233
|
// Slot 15: shadowAtlasTile i32 via Int32Array view (sentinel -1 default).
|
|
211
234
|
const i32 = new Int32Array(out.buffer);
|
|
212
|
-
i32[15] =
|
|
235
|
+
i32[15] =
|
|
236
|
+
snap.shadowAtlasTile >= 0
|
|
237
|
+
? snap.shadowAtlasTile
|
|
238
|
+
: snap.projectorAsset !== undefined && snap.lightViewProj !== undefined
|
|
239
|
+
? SPOT_LIGHT_PROJECTOR_ONLY_SENTINEL
|
|
240
|
+
: SPOT_LIGHT_SHADOW_TILE_SENTINEL;
|
|
241
|
+
// Slot 16 begins the fifth vec4 column. The remaining tail lanes stay zero
|
|
242
|
+
// so the std430 array stride is the explicit 80-byte contract.
|
|
243
|
+
out[16] = snap.shadowIntensity ?? 1;
|
|
213
244
|
return out;
|
|
214
245
|
}
|
|
215
246
|
|
|
@@ -275,8 +306,8 @@ export interface PointShadowSlotInfo {
|
|
|
275
306
|
* feat-20260612-point-light-shadows-urp-hdrp M4 / T-M4-4 (plan-strategy §D-8):
|
|
276
307
|
* the optional point `shadow` info threads through to bytes 52..64 as
|
|
277
308
|
* `(shadowAtlasLayer i32, near f32, far f32)`. Spot snapshots write their
|
|
278
|
-
* `shadowAtlasTile` directly into the same identity lane
|
|
279
|
-
* The shader reads `near`/`far`
|
|
309
|
+
* `shadowAtlasTile` directly into the same identity lane, put shadowIntensity
|
|
310
|
+
* in the `.z` lane, and the PCF kernel width in `.w`. The shader reads `near`/`far`
|
|
280
311
|
* through `bitcast<f32>(kind_and_pad.zw)` so the WGSL struct stays
|
|
281
312
|
* `kind_and_pad: vec4<u32>` (alignment + naga_oil compose unchanged). When
|
|
282
313
|
* `shadow` is undefined (no PointLightShadow) the lanes default to
|
|
@@ -288,6 +319,7 @@ export interface PointShadowSlotInfo {
|
|
|
288
319
|
export function packLightSlot(
|
|
289
320
|
snap: PointLightSnapshot | SpotLightSnapshot,
|
|
290
321
|
shadow?: PointShadowSlotInfo,
|
|
322
|
+
projectorSelected?: boolean,
|
|
291
323
|
): Float32Array {
|
|
292
324
|
const out = new Float32Array(16);
|
|
293
325
|
// position (vec3<f32> + invRangeSquared at lane .w)
|
|
@@ -309,15 +341,31 @@ export function packLightSlot(
|
|
|
309
341
|
// Float32Array: SPOT=1 must be 0x00000001, not f32(1.0) bits.
|
|
310
342
|
const u32 = new Uint32Array(out.buffer);
|
|
311
343
|
u32[12] = snap.kind === 'point' ? LightSlotKind.POINT : LightSlotKind.SPOT;
|
|
312
|
-
// Lanes 13..15 carry one kind-discriminated shadow
|
|
313
|
-
// layer/near/far; spot writes its snapshot tile and
|
|
344
|
+
// Lanes 13..15 carry one kind-discriminated shadow payload. Point keeps
|
|
345
|
+
// layer/near/far; spot writes its snapshot tile, shadowIntensity, and PCF
|
|
346
|
+
// kernel width.
|
|
314
347
|
const i32 = new Int32Array(out.buffer);
|
|
315
348
|
if (snap.kind === 'point' && shadow !== undefined) {
|
|
316
349
|
i32[13] = shadow.shadowAtlasLayer;
|
|
317
350
|
out[14] = shadow.near;
|
|
318
351
|
out[15] = shadow.far;
|
|
319
352
|
} else if (snap.kind === 'spot') {
|
|
320
|
-
|
|
353
|
+
// The optional argument is explicit at the record owner. Keeping the
|
|
354
|
+
// source-derived fallback preserves standalone packing fixtures while the
|
|
355
|
+
// production path marks only the accepted projector identity.
|
|
356
|
+
const hasProjector =
|
|
357
|
+
projectorSelected ?? (snap.projectorAsset !== undefined && snap.lightViewProj !== undefined);
|
|
358
|
+
const tile = snap.shadowAtlasTile >= 0 ? snap.shadowAtlasTile : 0;
|
|
359
|
+
i32[13] = hasProjector
|
|
360
|
+
? SPOT_LIGHT_PROJECTOR_FLAG | (tile & SPOT_LIGHT_TILE_MASK)
|
|
361
|
+
: snap.shadowAtlasTile >= 0
|
|
362
|
+
? snap.shadowAtlasTile
|
|
363
|
+
: SPOT_LIGHT_SHADOW_TILE_SENTINEL;
|
|
364
|
+
out[14] = snap.shadowIntensity ?? 1;
|
|
365
|
+
// HDRP has no separate 80-byte SpotLight payload. Reuse the otherwise
|
|
366
|
+
// unused spot `.w` lane so the cluster path consumes the same authored PCF
|
|
367
|
+
// width as the URP and volume paths.
|
|
368
|
+
out[15] = snap.pcfKernelSize ?? 3;
|
|
321
369
|
} else {
|
|
322
370
|
i32[13] = POINT_LIGHT_SHADOW_LAYER_SENTINEL;
|
|
323
371
|
// out[14] / out[15] remain zero (Float32Array zero-init).
|
|
@@ -17,12 +17,144 @@ export interface ResolvedMeshMaterialBinding {
|
|
|
17
17
|
readonly source: MeshMaterialBindingSource;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/** Lifecycle values projected from an already prepared resident binding. */
|
|
21
|
+
export type MeshMaterialBindingReadiness = 'ready' | 'pending' | 'failed' | 'last-known-good';
|
|
22
|
+
|
|
23
|
+
/** Structured producer failure retained by the renderer's bounded projection. */
|
|
24
|
+
export interface MeshMaterialBindingPreparationFailure {
|
|
25
|
+
readonly code: string;
|
|
26
|
+
readonly expected: string;
|
|
27
|
+
readonly hint: string;
|
|
28
|
+
readonly detail?: Readonly<Record<string, unknown>>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface MeshMaterialBindingSamplerObservation {
|
|
32
|
+
readonly handle: number;
|
|
33
|
+
readonly resident: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface MeshMaterialBindingTextureObservation {
|
|
37
|
+
readonly handle: number;
|
|
38
|
+
readonly mipLevelCount: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* One material-slot's bounded resident projection. The renderer reports only
|
|
43
|
+
* resources it actually resolved for the slot; Pack/AssetRegistry lifecycle
|
|
44
|
+
* records stay owned by the producer and are never copied here.
|
|
45
|
+
*/
|
|
46
|
+
export interface MeshMaterialBindingResidency {
|
|
47
|
+
readonly readiness: MeshMaterialBindingReadiness;
|
|
48
|
+
readonly samplers: readonly MeshMaterialBindingSamplerObservation[];
|
|
49
|
+
readonly textures: readonly MeshMaterialBindingTextureObservation[];
|
|
50
|
+
readonly preparationFailure?: MeshMaterialBindingPreparationFailure;
|
|
51
|
+
}
|
|
52
|
+
|
|
20
53
|
/** Public read-only observation of the bindings used by the last frame. */
|
|
21
54
|
export interface MeshMaterialBindingObservation {
|
|
22
55
|
readonly worldId: number;
|
|
23
56
|
readonly entityKey: number;
|
|
24
57
|
readonly bindings: readonly ResolvedMeshMaterialBinding[];
|
|
25
58
|
readonly diagnostics: readonly MeshMaterialBindingDiagnostic[];
|
|
59
|
+
/** One resident projection per resolved material slot. */
|
|
60
|
+
readonly residency: readonly MeshMaterialBindingResidency[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface MeshMaterialBindingSummary {
|
|
64
|
+
readonly total: number;
|
|
65
|
+
readonly ready: number;
|
|
66
|
+
readonly pending: number;
|
|
67
|
+
readonly failed: number;
|
|
68
|
+
readonly lastKnownGood: number;
|
|
69
|
+
readonly textureCount: number;
|
|
70
|
+
readonly samplerCount: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const EMPTY_RESIDENCY: MeshMaterialBindingResidency = Object.freeze({
|
|
74
|
+
readiness: 'pending',
|
|
75
|
+
samplers: Object.freeze([]),
|
|
76
|
+
textures: Object.freeze([]),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Build the sole renderer observation projection from the resident seam.
|
|
81
|
+
* Missing facts remain `pending`; they are never guessed from a URL, asset
|
|
82
|
+
* name, or authoring field. Slot cardinality is normalized so aggregation is
|
|
83
|
+
* deterministic even while a preparation candidate is incomplete.
|
|
84
|
+
*/
|
|
85
|
+
export function projectMeshMaterialBindingObservation(input: {
|
|
86
|
+
readonly worldId: number;
|
|
87
|
+
readonly entityKey: number;
|
|
88
|
+
readonly bindings: readonly ResolvedMeshMaterialBinding[];
|
|
89
|
+
readonly diagnostics: readonly MeshMaterialBindingDiagnostic[];
|
|
90
|
+
readonly residency?: readonly MeshMaterialBindingResidency[];
|
|
91
|
+
}): MeshMaterialBindingObservation {
|
|
92
|
+
const residency = input.bindings.map((_, index) => {
|
|
93
|
+
const value = input.residency?.[index] ?? EMPTY_RESIDENCY;
|
|
94
|
+
return Object.freeze({
|
|
95
|
+
...value,
|
|
96
|
+
samplers: Object.freeze(value.samplers.map((sampler) => Object.freeze({ ...sampler }))),
|
|
97
|
+
textures: Object.freeze(value.textures.map((texture) => Object.freeze({ ...texture }))),
|
|
98
|
+
...(value.preparationFailure === undefined
|
|
99
|
+
? {}
|
|
100
|
+
: {
|
|
101
|
+
preparationFailure: Object.freeze({
|
|
102
|
+
...value.preparationFailure,
|
|
103
|
+
...(value.preparationFailure.detail === undefined
|
|
104
|
+
? {}
|
|
105
|
+
: { detail: Object.freeze({ ...value.preparationFailure.detail }) }),
|
|
106
|
+
}),
|
|
107
|
+
}),
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
worldId: input.worldId,
|
|
112
|
+
entityKey: input.entityKey,
|
|
113
|
+
bindings: Object.freeze([...input.bindings]),
|
|
114
|
+
diagnostics: Object.freeze([...input.diagnostics]),
|
|
115
|
+
residency: Object.freeze(residency),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Recompute bounded readiness/resource counts from retained observations. */
|
|
120
|
+
export function summarizeMeshMaterialBindings(
|
|
121
|
+
observations: readonly MeshMaterialBindingObservation[],
|
|
122
|
+
): MeshMaterialBindingSummary {
|
|
123
|
+
let ready = 0;
|
|
124
|
+
let pending = 0;
|
|
125
|
+
let failed = 0;
|
|
126
|
+
let lastKnownGood = 0;
|
|
127
|
+
let textureCount = 0;
|
|
128
|
+
let samplerCount = 0;
|
|
129
|
+
for (const observation of observations) {
|
|
130
|
+
for (const residency of observation.residency) {
|
|
131
|
+
switch (residency.readiness) {
|
|
132
|
+
case 'ready':
|
|
133
|
+
ready += 1;
|
|
134
|
+
break;
|
|
135
|
+
case 'pending':
|
|
136
|
+
pending += 1;
|
|
137
|
+
break;
|
|
138
|
+
case 'failed':
|
|
139
|
+
failed += 1;
|
|
140
|
+
break;
|
|
141
|
+
case 'last-known-good':
|
|
142
|
+
lastKnownGood += 1;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
textureCount += residency.textures.length;
|
|
146
|
+
samplerCount += residency.samplers.length;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
total: ready + pending + failed + lastKnownGood,
|
|
151
|
+
ready,
|
|
152
|
+
pending,
|
|
153
|
+
failed,
|
|
154
|
+
lastKnownGood,
|
|
155
|
+
textureCount,
|
|
156
|
+
samplerCount,
|
|
157
|
+
};
|
|
26
158
|
}
|
|
27
159
|
|
|
28
160
|
export type ResolveMeshMaterialBindingsResult =
|
package/src/pbr-pipeline.ts
CHANGED
|
@@ -140,7 +140,7 @@ export function buildPbrMaterialUserRegionEntries(
|
|
|
140
140
|
// material-UBO contract. derive() emits binding 0 as the first numeric run's
|
|
141
141
|
// merged UBO; an empty schema has no binding-0 UBO and needs no patch.
|
|
142
142
|
const ubo = entries[0];
|
|
143
|
-
if (ubo !== undefined && ubo.binding === 0 && ubo.buffer
|
|
143
|
+
if (ubo !== undefined && ubo.binding === 0 && ubo.buffer?.type === 'uniform') {
|
|
144
144
|
entries[0] = {
|
|
145
145
|
binding: 0,
|
|
146
146
|
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
@@ -325,6 +325,8 @@ export const INJECTION_KIND_LENGTHS = {
|
|
|
325
325
|
*/
|
|
326
326
|
export interface PbrCaps {
|
|
327
327
|
readonly storageBuffer: boolean;
|
|
328
|
+
/** Whether the device can carry the optional SpotLight projector texture. */
|
|
329
|
+
readonly projectorAvailable?: boolean;
|
|
328
330
|
}
|
|
329
331
|
|
|
330
332
|
/**
|
|
@@ -376,11 +378,13 @@ export interface PbrCaps {
|
|
|
376
378
|
*/
|
|
377
379
|
export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[] {
|
|
378
380
|
const lightBufType: GPUBufferBindingType = caps.storageBuffer ? 'read-only-storage' : 'uniform';
|
|
379
|
-
|
|
381
|
+
const entries: GPUBindGroupLayoutEntry[] = [
|
|
380
382
|
{
|
|
381
383
|
binding: 0,
|
|
382
384
|
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
383
|
-
|
|
385
|
+
// View captures use the same bind group with a per-face view slot.
|
|
386
|
+
// Keeping this dynamic is also valid for the display slot at offset 0.
|
|
387
|
+
buffer: { type: 'uniform', hasDynamicOffset: true },
|
|
384
388
|
},
|
|
385
389
|
{
|
|
386
390
|
binding: 1,
|
|
@@ -469,12 +473,32 @@ export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[]
|
|
|
469
473
|
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
470
474
|
texture: { sampleType: 'depth', viewDimension: '2d' },
|
|
471
475
|
},
|
|
472
|
-
{
|
|
473
|
-
binding: 10,
|
|
474
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
475
|
-
buffer: { type: 'uniform', hasDynamicOffset: true },
|
|
476
|
-
},
|
|
477
476
|
];
|
|
477
|
+
// The projector is optional, but when present it is a sampled texture in
|
|
478
|
+
// the fragment stage. Keep it out of the low-limit view layout so the
|
|
479
|
+
// remaining HDRP PBR ABI stays within WebGPU's minimum 16 sampled textures.
|
|
480
|
+
// The corresponding PROJECTOR_AVAILABLE shader variant is selected from
|
|
481
|
+
// the same device capability bit and returns a white modulation.
|
|
482
|
+
if (caps.projectorAvailable !== false) {
|
|
483
|
+
entries.push(
|
|
484
|
+
{
|
|
485
|
+
binding: 11,
|
|
486
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
487
|
+
texture: { sampleType: 'float', viewDimension: '2d' },
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
binding: 12,
|
|
491
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
492
|
+
sampler: { type: 'filtering' },
|
|
493
|
+
},
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
entries.push({
|
|
497
|
+
binding: 10,
|
|
498
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
499
|
+
buffer: { type: 'uniform', hasDynamicOffset: true },
|
|
500
|
+
});
|
|
501
|
+
return entries;
|
|
478
502
|
}
|
|
479
503
|
|
|
480
504
|
// ─── PBR pipeline layout factory ────────────────────────────────────────────
|
|
@@ -578,6 +602,22 @@ export function isSkinnedShadowCasterVariant(
|
|
|
578
602
|
);
|
|
579
603
|
}
|
|
580
604
|
|
|
605
|
+
export type PipelineGroup2Contract = 'mesh' | 'skin' | 'cluster' | 'skin-cluster';
|
|
606
|
+
|
|
607
|
+
/** Resolve group(2) from the composed WGSL artifact used to build the PSO. */
|
|
608
|
+
export function resolvePipelineGroup2Contract(source: string): PipelineGroup2Contract {
|
|
609
|
+
const withoutComments = source.replace(/\/\*[\s\S]*?\*\//gu, '').replace(/\/\/.*$/gmu, '');
|
|
610
|
+
const bindings = [
|
|
611
|
+
...withoutComments.matchAll(/@group\s*\(\s*2\s*\)\s*@binding\s*\(\s*(\d+)\s*\)/gu),
|
|
612
|
+
].map((match) => Number(match[1]));
|
|
613
|
+
const hasSkinBindings = bindings.includes(1) || bindings.includes(2);
|
|
614
|
+
const hasClusterBindings = bindings.some((binding) => binding >= 3);
|
|
615
|
+
if (hasSkinBindings && hasClusterBindings) return 'skin-cluster';
|
|
616
|
+
if (hasSkinBindings) return 'skin';
|
|
617
|
+
if (hasClusterBindings) return 'cluster';
|
|
618
|
+
return 'mesh';
|
|
619
|
+
}
|
|
620
|
+
|
|
581
621
|
/** Returns true for the engine-shipped standard-PBR material shader family. */
|
|
582
622
|
export function isStandardPbrMaterialShader(shaderId: string | undefined): boolean {
|
|
583
623
|
return (
|
|
@@ -609,9 +649,10 @@ export function isStandardPbrMaterialShader(shaderId: string | undefined): boole
|
|
|
609
649
|
|
|
610
650
|
/**
|
|
611
651
|
* Build the PBR skin pipeline layout (4 slots `[view, material,
|
|
612
|
-
* mesh-array(
|
|
652
|
+
* mesh-array(3-entry), instances]`). View / material / instances BGLs are
|
|
613
653
|
* shared with the standard-PBR layout (passed in via `pbr` bundle); the only
|
|
614
|
-
* new BGL is the
|
|
654
|
+
* new BGL is the 3-entry mesh-array slot for `meshes` + current/previous
|
|
655
|
+
* `palette` buffers.
|
|
615
656
|
*
|
|
616
657
|
* Throws on each `createBindGroupLayout` / `createPipelineLayout` Result
|
|
617
658
|
* failure -- the engine bootstrap path wraps the call in `runShimSyncStep`
|
|
@@ -622,8 +663,9 @@ export function buildPbrSkinLayouts(
|
|
|
622
663
|
caps: PbrCaps,
|
|
623
664
|
pbr: PbrPipelineLayoutBundle,
|
|
624
665
|
): PbrPipelineLayoutBundle {
|
|
625
|
-
//
|
|
626
|
-
//
|
|
666
|
+
// 3-entry mesh-array BGL: binding 0 meshes + binding 1 current palette
|
|
667
|
+
// + binding 2 previous palette. All use dynamic offsets for the same
|
|
668
|
+
// per-entity window contract.
|
|
627
669
|
const skinMeshArrayBglRes = device.createBindGroupLayout(
|
|
628
670
|
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
629
671
|
kind: 'pbr-skin-mesh-array',
|
|
@@ -654,6 +696,40 @@ export function buildPbrSkinLayouts(
|
|
|
654
696
|
};
|
|
655
697
|
}
|
|
656
698
|
|
|
699
|
+
/** Project the canonical group(2) resources for a PBR skin draw. */
|
|
700
|
+
export function createPbrSkinMeshBindGroupEntries(
|
|
701
|
+
meshBuffer: Buffer,
|
|
702
|
+
meshSize: number,
|
|
703
|
+
paletteBuffer: Buffer,
|
|
704
|
+
paletteWindowBytes: number,
|
|
705
|
+
): BindGroupEntry[] {
|
|
706
|
+
return [
|
|
707
|
+
{
|
|
708
|
+
binding: 0,
|
|
709
|
+
resource: { kind: 'buffer', value: { buffer: meshBuffer, offset: 0, size: meshSize } },
|
|
710
|
+
},
|
|
711
|
+
...[1, 2].map((binding) => ({
|
|
712
|
+
binding,
|
|
713
|
+
resource: {
|
|
714
|
+
kind: 'buffer' as const,
|
|
715
|
+
value: {
|
|
716
|
+
buffer: paletteBuffer,
|
|
717
|
+
offset: 0,
|
|
718
|
+
size: paletteWindowBytes,
|
|
719
|
+
},
|
|
720
|
+
},
|
|
721
|
+
})),
|
|
722
|
+
];
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/** Project all dynamic offsets for the canonical PBR skin group(2) shape. */
|
|
726
|
+
export function pbrSkinMeshDynamicOffsets(
|
|
727
|
+
meshOffset: number,
|
|
728
|
+
paletteOffset: number,
|
|
729
|
+
): readonly [number, number, number] {
|
|
730
|
+
return [meshOffset, paletteOffset, paletteOffset];
|
|
731
|
+
}
|
|
732
|
+
|
|
657
733
|
// ─── Unlit material BGL factory ─────────────────────────────────────────────
|
|
658
734
|
|
|
659
735
|
/**
|
|
@@ -741,7 +817,7 @@ export type { BindGroup };
|
|
|
741
817
|
// existing behaviour (plan-strategy D-4 "pbr / unlit / sprite-atlas
|
|
742
818
|
// behaviour unchanged" / requirements Edge Cases).
|
|
743
819
|
//
|
|
744
|
-
// Variant set string format mirrors the
|
|
820
|
+
// Variant set string format mirrors the Standard boot variant /
|
|
745
821
|
// HDRP variant set string idiom in `pipeline-spec.ts` (`+`-separated kv
|
|
746
822
|
// pairs); the record stage threads this string through the per-shader
|
|
747
823
|
// pipeline-cache key + lazy-build `getMaterialShaderPipeline` lookup.
|
|
@@ -784,12 +860,13 @@ export const SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET = '';
|
|
|
784
860
|
* - `'unlit-material'` — 7 entries: base PBR material only (no inject)
|
|
785
861
|
* - `'hdrp-7-slot'` — 7 entries (binding 0 + 3..8): HDRP cluster + SSAO group(2) BGL
|
|
786
862
|
* 2. Caps-driven literal shapes (no shader):
|
|
787
|
-
* - `'pbr-view'` —
|
|
788
|
-
*
|
|
789
|
-
*
|
|
863
|
+
* - `'pbr-view'` — 12 entries: view UBO + lights + shadow bindings,
|
|
864
|
+
* projector texture/sampler (11/12), and the Points/Lines UBO (10)
|
|
865
|
+
* (directional 3/4, point 5/6, cascade 7, spot atlas 8; the former
|
|
866
|
+
* spot lightViewProj matrices moved into the View UBO)
|
|
790
867
|
* - `'pbr-mesh-array'` — 1 entry: per-entity mesh SSBO (dynamic-offset)
|
|
791
868
|
* - `'pbr-instances'` — 1 entry: per-instance SSBO (no dynamic-offset)
|
|
792
|
-
* - `'pbr-skin-mesh-array'` —
|
|
869
|
+
* - `'pbr-skin-mesh-array'` — 3 entries: meshes + current/previous palette
|
|
793
870
|
* 3. Attachment-driven (fullscreen post-process):
|
|
794
871
|
* - `'fullscreen-post'` — 2 entries: input texture + sampler. The texture
|
|
795
872
|
* `sampleType` is derived from `spec.attachments` (plan §R3 fix):
|
|
@@ -832,17 +909,20 @@ export interface BindGroupLayoutDescriptorOutput {
|
|
|
832
909
|
}
|
|
833
910
|
|
|
834
911
|
/** Build the canonical HDRP group(2) bind-group layout. */
|
|
835
|
-
export function createHdrpBindGroupLayoutDescriptor(
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
const meshBufType: GPUBufferBindingType = storageBuffer ? 'read-only-storage' : 'uniform';
|
|
839
|
-
const clusterBufType: GPUBufferBindingType = storageBuffer ? 'read-only-storage' : 'uniform';
|
|
912
|
+
export function createHdrpBindGroupLayoutDescriptor(): BindGroupLayoutDescriptor {
|
|
913
|
+
const meshBufType: GPUBufferBindingType = 'read-only-storage';
|
|
914
|
+
const clusterBufType: GPUBufferBindingType = 'read-only-storage';
|
|
840
915
|
return {
|
|
841
916
|
label: 'hdrp-unified-bgl-group2',
|
|
842
917
|
entries: [
|
|
843
918
|
{
|
|
844
919
|
binding: 0,
|
|
845
|
-
|
|
920
|
+
// Standard fragment lighting (transmission/refraction and clustered
|
|
921
|
+
// evaluation) reads the same mesh transform window as the vertex
|
|
922
|
+
// stage. Keep this visibility in the HDRP descriptor aligned with
|
|
923
|
+
// the URP mesh-array descriptor; restricting it to vertex makes the
|
|
924
|
+
// HDRP pipeline invalid when fs_main accesses `meshes[0]`.
|
|
925
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
846
926
|
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
847
927
|
},
|
|
848
928
|
// Bindings 1 and 2 stay absent for the URP physical isolation gap.
|
|
@@ -880,6 +960,33 @@ export function createHdrpBindGroupLayoutDescriptor(
|
|
|
880
960
|
};
|
|
881
961
|
}
|
|
882
962
|
|
|
963
|
+
/** Build the HDRP group(2) layout for the clustered skin variant. */
|
|
964
|
+
export function createHdrpSkinBindGroupLayoutDescriptor(): BindGroupLayoutDescriptor {
|
|
965
|
+
const base = createHdrpBindGroupLayoutDescriptor();
|
|
966
|
+
const baseEntries = base.entries;
|
|
967
|
+
if (baseEntries === undefined || baseEntries[0] === undefined) {
|
|
968
|
+
throw new Error('HDRP base group(2) layout must declare mesh binding 0');
|
|
969
|
+
}
|
|
970
|
+
const paletteType: GPUBufferBindingType = 'read-only-storage';
|
|
971
|
+
return {
|
|
972
|
+
label: 'hdrp-skin-unified-bgl-group2',
|
|
973
|
+
entries: [
|
|
974
|
+
baseEntries[0],
|
|
975
|
+
{
|
|
976
|
+
binding: 1,
|
|
977
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
978
|
+
buffer: { type: paletteType, hasDynamicOffset: true },
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
binding: 2,
|
|
982
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
983
|
+
buffer: { type: paletteType, hasDynamicOffset: true },
|
|
984
|
+
},
|
|
985
|
+
...baseEntries.slice(1),
|
|
986
|
+
],
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
|
|
883
990
|
/**
|
|
884
991
|
* Build a `GPUBindGroupLayoutDescriptor` from a PipelineSpec, dispatching on
|
|
885
992
|
* `options.kind` to one of 9 closed BGL shapes (D-13 round-2).
|
|
@@ -1014,6 +1121,11 @@ export function buildBindGroupLayoutDescriptor(
|
|
|
1014
1121
|
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1015
1122
|
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
1016
1123
|
},
|
|
1124
|
+
{
|
|
1125
|
+
binding: 2,
|
|
1126
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1127
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
1128
|
+
},
|
|
1017
1129
|
],
|
|
1018
1130
|
};
|
|
1019
1131
|
}
|
|
@@ -1045,10 +1157,10 @@ export function buildBindGroupLayoutDescriptor(
|
|
|
1045
1157
|
};
|
|
1046
1158
|
}
|
|
1047
1159
|
case 'hdrp-7-slot': {
|
|
1048
|
-
//
|
|
1049
|
-
//
|
|
1050
|
-
|
|
1051
|
-
const desc = createHdrpBindGroupLayoutDescriptor(
|
|
1160
|
+
// Standard unified BGL for group(2): 9 entries (binding 0 + 3..8).
|
|
1161
|
+
// Cluster variants are admitted only when storage buffers are present;
|
|
1162
|
+
// there is no uniform-backed cluster shape.
|
|
1163
|
+
const desc = createHdrpBindGroupLayoutDescriptor();
|
|
1052
1164
|
return {
|
|
1053
1165
|
label: desc.label ?? 'hdrp-unified-bgl-group2',
|
|
1054
1166
|
entries: [...(desc.entries ?? [])],
|