@forgeax/engine-render 0.1.20 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +365 -29
- package/dist/assembly/backend-contract.d.ts +13 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/device-feature-admission.d.ts +18 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -0
- package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
- package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +30 -19
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +19 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/render-target-host.d.ts +46 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -0
- package/dist/assets/render-asset-port.d.ts.map +1 -1
- package/dist/authoring.mjs +4 -1
- package/dist/authoring.mjs.map +1 -1
- package/dist/capture/cube-views.d.ts +21 -0
- package/dist/capture/cube-views.d.ts.map +1 -0
- package/dist/capture/scheduler.d.ts +54 -0
- package/dist/capture/scheduler.d.ts.map +1 -0
- package/dist/{chunk-PCHBPYML.mjs → chunk-4L3P6DT5.mjs} +2 -2
- package/dist/chunk-4L3P6DT5.mjs.map +1 -0
- package/dist/{chunk-VFPLTKCU.mjs → chunk-4NPUASZR.mjs} +15 -4
- package/dist/chunk-4NPUASZR.mjs.map +1 -0
- package/dist/chunk-DIYW3M5D.mjs +5085 -0
- package/dist/chunk-DIYW3M5D.mjs.map +1 -0
- package/dist/chunk-FBC4R44J.mjs +1003 -0
- package/dist/chunk-FBC4R44J.mjs.map +1 -0
- package/dist/{chunk-CDTWTHZR.mjs → chunk-FF7K3FSO.mjs} +474 -168
- package/dist/chunk-FF7K3FSO.mjs.map +1 -0
- package/dist/chunk-HZUPSYW7.mjs +1104 -0
- package/dist/chunk-HZUPSYW7.mjs.map +1 -0
- package/dist/{chunk-TBQJOK2L.mjs → chunk-QODA5UKU.mjs} +321 -269
- package/dist/chunk-QODA5UKU.mjs.map +1 -0
- package/dist/chunk-YALPS44A.mjs +296 -0
- package/dist/chunk-YALPS44A.mjs.map +1 -0
- package/dist/{chunk-4XINDLAY.mjs → chunk-ZUWKAZ2I.mjs} +1963 -2178
- package/dist/chunk-ZUWKAZ2I.mjs.map +1 -0
- package/dist/cluster-binner.d.ts +5 -0
- package/dist/cluster-binner.d.ts.map +1 -1
- package/dist/components/camera.d.ts +1 -0
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/cube-camera.d.ts +20 -0
- package/dist/components/cube-camera.d.ts.map +1 -0
- package/dist/components/directional-light.d.ts +11 -2
- package/dist/components/directional-light.d.ts.map +1 -1
- package/dist/components/directional-shadow-filter.d.ts +25 -0
- package/dist/components/directional-shadow-filter.d.ts.map +1 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts +4 -0
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/light-probe.d.ts +9 -0
- package/dist/components/light-probe.d.ts.map +1 -0
- package/dist/components/rect-area-light.d.ts +12 -0
- package/dist/components/rect-area-light.d.ts.map +1 -0
- package/dist/components/reflection-probe.d.ts +17 -0
- package/dist/components/reflection-probe.d.ts.map +1 -0
- package/dist/components/scene-instance.d.ts +4 -0
- package/dist/components/scene-instance.d.ts.map +1 -1
- package/dist/components/spot-light.d.ts +3 -0
- package/dist/components/spot-light.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +14836 -9620
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +8 -1
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/device/lifecycle-transaction.d.ts +2 -0
- package/dist/device/lifecycle-transaction.d.ts.map +1 -0
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +5 -0
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/gpu-driven.d.ts +26 -0
- package/dist/errors/gpu-driven.d.ts.map +1 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +9 -1
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +166 -93
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/directional-shadow-projection.d.ts +23 -0
- package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
- package/dist/extract/environment.d.ts +14 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +50 -0
- package/dist/extract/gpu-driven.d.ts.map +1 -0
- package/dist/extract/visibility.d.ts.map +1 -1
- package/dist/features/fullscreen.d.ts.map +1 -1
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +10 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +13 -2
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +34 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts +63 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +97 -2
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/view-gpu.d.ts +64 -1
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts +14 -0
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +8 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-usage.d.ts +0 -1
- package/dist/gpu-usage.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +21 -19
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +4 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/kernel-cache.d.ts +36 -0
- package/dist/ibl/kernel-cache.d.ts.map +1 -0
- package/dist/index.d.ts +39 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +91 -6
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +214 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances-derived-bounds.d.ts +50 -0
- package/dist/instances-derived-bounds.d.ts.map +1 -0
- package/dist/internal.d.ts +9 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +23 -2
- package/dist/internal.mjs.map +1 -1
- package/dist/light-buffer-layout.d.ts +58 -140
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +54 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +38 -14
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts +2 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
- package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
- package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
- package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
- package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
- package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
- package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts +4 -13
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline/standard-profile.d.ts +5 -26
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +2 -0
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +40 -7
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/point-shadow-inspection.d.ts +21 -0
- package/dist/point-shadow-inspection.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
- package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/resources.d.ts +72 -0
- package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
- package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
- package/dist/prepare/extended-lighting/state.d.ts +24 -0
- package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +33 -36
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +78 -24
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts +5 -0
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +16 -6
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
- package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
- package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/index.d.ts +8 -0
- package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
- package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/session.d.ts +43 -0
- package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +20 -3
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +0 -20
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +6 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +25 -2
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +98 -6
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +119 -4
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +7 -5
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/reflection/filter.d.ts +22 -0
- package/dist/reflection/filter.d.ts.map +1 -0
- package/dist/reflection/gpu-table.d.ts +25 -0
- package/dist/reflection/gpu-table.d.ts.map +1 -0
- package/dist/reflection/inspection.d.ts +10 -0
- package/dist/reflection/inspection.d.ts.map +1 -0
- package/dist/reflection/projection.d.ts +140 -0
- package/dist/reflection/projection.d.ts.map +1 -0
- package/dist/reflection/record-owner.d.ts +60 -0
- package/dist/reflection/record-owner.d.ts.map +1 -0
- package/dist/render-contract.d.ts +62 -14
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +1 -0
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +49 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +160 -31
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +28 -2
- package/dist/render-system.d.ts.map +1 -1
- package/dist/renderer.d.ts +43 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/scene/probe-blend-record.d.ts +22 -0
- package/dist/scene/probe-blend-record.d.ts.map +1 -0
- package/dist/scene/probe-blend.d.ts +142 -0
- package/dist/scene/probe-blend.d.ts.map +1 -0
- package/dist/scene/render-scene-types.d.ts +0 -6
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +117 -9
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/visibility/bounds.d.ts +20 -0
- package/dist/scene/visibility/bounds.d.ts.map +1 -0
- package/dist/scene/visibility/budget.d.ts +16 -0
- package/dist/scene/visibility/budget.d.ts.map +1 -0
- package/dist/scene/visibility/facet.d.ts +73 -0
- package/dist/scene/visibility/facet.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
- package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
- package/dist/scene/visibility/gpu-lod.d.ts +46 -0
- package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
- package/dist/scene/visibility/inspection.d.ts +132 -0
- package/dist/scene/visibility/inspection.d.ts.map +1 -0
- package/dist/scene/visibility/lod-selector.d.ts +25 -0
- package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
- package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
- package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
- package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
- package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
- package/dist/scene/visibility/types.d.ts +34 -0
- package/dist/scene/visibility/types.d.ts.map +1 -0
- package/dist/shadow-atlas.d.ts +3 -3
- package/dist/shadow-atlas.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +3 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/ssr/admission.d.ts +122 -0
- package/dist/ssr/admission.d.ts.map +1 -0
- package/dist/ssr/composition.d.ts +32 -0
- package/dist/ssr/composition.d.ts.map +1 -0
- package/dist/ssr/errors.d.ts +39 -0
- package/dist/ssr/errors.d.ts.map +1 -0
- package/dist/ssr/identity.d.ts +13 -0
- package/dist/ssr/identity.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +1 -1
- package/dist/targets/contracts.d.ts +66 -0
- package/dist/targets/contracts.d.ts.map +1 -0
- package/dist/targets/graph-projection.d.ts +29 -0
- package/dist/targets/graph-projection.d.ts.map +1 -0
- package/dist/targets/material-source.d.ts +34 -0
- package/dist/targets/material-source.d.ts.map +1 -0
- package/dist/targets/owner.d.ts +32 -0
- package/dist/targets/owner.d.ts.map +1 -0
- package/dist/targets/physical.d.ts +18 -0
- package/dist/targets/physical.d.ts.map +1 -0
- package/dist/targets/readback.d.ts +39 -0
- package/dist/targets/readback.d.ts.map +1 -0
- package/dist/temporal/frame-coordinator.d.ts +13 -0
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +2 -0
- package/dist/temporal/frame.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -5
- package/dist/temporal/view.d.ts +7 -0
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/tilemap-chunk-extract-system.d.ts +1 -1
- package/dist/typed-render-graph-primitives.d.ts +5 -1
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +1 -1
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +9 -5
- package/dist/volume/passes.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
- package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
- package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
- package/src/__tests__/cluster-binner.unit.test.ts +35 -0
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +12 -2
- package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
- package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
- package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
- package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
- package/src/__tests__/cube-camera.integration.test.ts +42 -0
- package/src/__tests__/detached-inspection.integration.test.ts +6 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +85 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +62 -6
- package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
- package/src/__tests__/environment-generation.integration.test.ts +16 -0
- package/src/__tests__/evidence-identity.ts +13 -0
- package/src/__tests__/evidence-identity.unit.test.ts +24 -0
- package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
- package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
- package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
- package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
- package/src/__tests__/factory-contract.integration.test.ts +288 -29
- package/src/__tests__/fog-component.unit.test.ts +67 -0
- package/src/__tests__/fog.integration.test.ts +86 -0
- package/src/__tests__/frame-observation.contract.test.ts +15 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -8
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +18 -1
- package/src/__tests__/gpu-driven-production.integration.test.ts +579 -17
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +101 -6
- package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
- package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
- package/src/__tests__/gpu-lod-evidence.ts +188 -0
- package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
- package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
- package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
- package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
- package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
- package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
- package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
- package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
- package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
- package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
- package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
- package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
- package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
- package/src/__tests__/gpu-scene.unit.test.ts +49 -3
- package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
- package/src/__tests__/instances-culling.integration.test.ts +94 -0
- package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
- package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
- package/src/__tests__/light-inspection.unit.test.ts +55 -0
- package/src/__tests__/light-resource-error.unit.test.ts +43 -0
- package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
- package/src/__tests__/lod-bounds.unit.test.ts +42 -0
- package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
- package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
- package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
- package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
- package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
- package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
- package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
- package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
- package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
- package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
- package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
- package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
- package/src/__tests__/lod-selector.profile.test.ts +35 -0
- package/src/__tests__/lod-selector.unit.test.ts +68 -0
- package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
- package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
- package/src/__tests__/ltc-resources.unit.test.ts +32 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +17 -0
- package/src/__tests__/material-observation.integration.test.ts +101 -0
- package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
- package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
- package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
- package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
- package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
- package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
- package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
- package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
- package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
- package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
- package/src/__tests__/occlusion-query.evidence.ts +178 -0
- package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
- package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
- package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
- package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
- package/src/__tests__/probe-bindings.unit.test.ts +200 -0
- package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
- package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
- package/src/__tests__/probe-capacity.integration.test.ts +97 -0
- package/src/__tests__/probe-recovery.integration.test.ts +104 -0
- package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
- package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
- package/src/__tests__/profiler-phase-token.test.ts +1 -0
- package/src/__tests__/public-surface.test-d.ts +10 -0
- package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
- package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
- package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
- package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
- package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
- package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
- package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
- package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
- package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
- package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
- package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
- package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +19 -3
- package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
- package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
- package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
- package/src/__tests__/render-target-admission.unit.test.ts +80 -0
- package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
- package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
- package/src/__tests__/render-target-material-source.test-d.ts +30 -0
- package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
- package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
- package/src/__tests__/render-target-owner.unit.test.ts +122 -0
- package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
- package/src/__tests__/render-target-public-schema.json +107 -0
- package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
- package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
- package/src/__tests__/render-target-readback.integration.test.ts +90 -0
- package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +124 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
- package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
- package/src/__tests__/skin-motion-regression.unit.test.ts +154 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +13 -4
- package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
- package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
- package/src/__tests__/ssr-composition.unit.test.ts +46 -0
- package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
- package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
- package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
- package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +299 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +15 -5
- package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
- package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
- package/src/__tests__/standard-lighting-write.unit.test.ts +441 -0
- package/src/__tests__/standard-lighting.integration.test.ts +67 -0
- package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
- package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
- package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
- package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -38
- package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
- package/src/__tests__/temporal-view.unit.test.ts +3 -3
- package/src/__tests__/transmission-prewarm.unit.test.ts +69 -0
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
- package/src/__tests__/visibility-budget.integration.test.ts +140 -0
- package/src/__tests__/visibility-budget.unit.test.ts +70 -0
- package/src/__tests__/visibility-extract.integration.test.ts +11 -6
- package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
- package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
- package/src/assembly/backend-contract.ts +13 -0
- package/src/assembly/device-feature-admission.ts +80 -0
- package/src/assembly/directional-shadow-inspection.ts +122 -0
- package/src/assembly/factory.ts +1411 -366
- package/src/assembly/host-contract.ts +35 -0
- package/src/assembly/render-target-host.ts +847 -0
- package/src/assets/asset-decoders.ts +1 -1
- package/src/assets/render-asset-port.ts +7 -1
- package/src/capture/cube-views.ts +69 -0
- package/src/capture/scheduler.ts +265 -0
- package/src/cluster-binner.ts +31 -0
- package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
- package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
- package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
- package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
- package/src/components/camera.ts +4 -0
- package/src/components/cube-camera.ts +52 -0
- package/src/components/directional-light.ts +22 -2
- package/src/components/directional-shadow-filter.ts +57 -0
- package/src/components/index.ts +5 -0
- package/src/components/light-helpers.ts +133 -8
- package/src/components/light-probe.ts +13 -0
- package/src/components/rect-area-light.ts +15 -0
- package/src/components/reflection-probe.ts +49 -0
- package/src/components/scene-instance.ts +6 -0
- package/src/components/spot-light.ts +3 -0
- package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
- package/src/device/gpu-residency.ts +140 -9
- package/src/device/lifecycle-transaction.ts +12 -0
- package/src/environment/frame.ts +6 -24
- package/src/environment/lifecycle.ts +20 -1
- package/src/errors/gpu-driven.ts +92 -0
- package/src/errors/index.ts +1 -0
- package/src/errors/recover.ts +32 -0
- package/src/errors/render.ts +341 -143
- package/src/extract/camera.ts +3 -3
- package/src/extract/directional-shadow-projection.ts +61 -0
- package/src/extract/environment.ts +57 -0
- package/src/extract/gpu-driven.ts +108 -0
- package/src/extract/visibility.ts +2 -1
- package/src/features/fullscreen.ts +3 -0
- package/src/features/targets.ts +4 -1
- package/src/features/types.ts +10 -0
- package/src/fullscreen-post-process-pass.ts +43 -2
- package/src/gpu-driven/batch-topology.ts +207 -28
- package/src/gpu-driven/prepared-draw.ts +208 -0
- package/src/gpu-driven/production-raster.ts +953 -43
- package/src/gpu-driven/view-gpu.ts +411 -29
- package/src/gpu-scene-schema.ts +13 -0
- package/src/gpu-scene.ts +140 -64
- package/src/gpu-usage.ts +0 -1
- package/src/hdrp-buffers.ts +169 -63
- package/src/ibl/IblPipelineCache.ts +11 -0
- package/src/ibl/kernel-cache.ts +88 -0
- package/src/index.ts +222 -0
- package/src/inspection-types.ts +276 -1
- package/src/instances-derived-bounds.ts +171 -0
- package/src/internal.ts +38 -0
- package/src/light-buffer-layout.ts +155 -310
- package/src/materials.ts +16 -2
- package/src/mesh-material-bindings.ts +132 -0
- package/src/pbr-pipeline.ts +255 -60
- package/src/pipeline/standard-forward-lane.ts +93 -16
- package/src/pipeline/standard-lighting/errors.ts +6 -0
- package/src/pipeline/standard-lighting/graph.ts +158 -0
- package/src/pipeline/standard-lighting/inspection.ts +88 -0
- package/src/pipeline/standard-lighting/layout.ts +31 -0
- package/src/pipeline/standard-lighting/light-frame.ts +35 -0
- package/src/pipeline/standard-lighting/membership.ts +43 -0
- package/src/pipeline/standard-lighting/prepare.ts +37 -0
- package/src/pipeline/standard-lighting/topology.ts +120 -0
- package/src/pipeline/standard-lighting/transport.ts +78 -0
- package/src/pipeline/standard-pipeline.ts +124 -193
- package/src/pipeline/standard-post.ts +26 -7
- package/src/pipeline/standard-profile.ts +17 -47
- package/src/pipeline-builder.ts +5 -2
- package/src/pipeline-spec.ts +95 -21
- package/src/plugin.ts +4 -0
- package/src/point-shadow-inspection.ts +55 -0
- package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
- package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
- package/src/prepare/extended-lighting/resources.ts +389 -0
- package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
- package/src/prepare/extended-lighting/state.ts +92 -0
- package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
- package/src/record/__tests__/temporal-payload.unit.test.ts +64 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +20 -1
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
- package/src/record/frame-lighting.ts +591 -452
- package/src/record/frame-snapshot.ts +92 -39
- package/src/record/frame-targets.ts +17 -0
- package/src/record/frame.ts +662 -158
- package/src/record/gpu-pass-timing/contract.ts +180 -0
- package/src/record/gpu-pass-timing/errors.ts +34 -0
- package/src/record/gpu-pass-timing/index.ts +37 -0
- package/src/record/gpu-pass-timing/parser.ts +97 -0
- package/src/record/gpu-pass-timing/session.ts +938 -0
- package/src/record/gpu-timing.ts +112 -39
- package/src/record/helpers.ts +0 -58
- package/src/record/main-pass-geometry.ts +324 -119
- package/src/record/main-pass-material.ts +103 -10
- package/src/record/main-pass-sprite-draws.ts +99 -103
- package/src/record/main-pass.ts +71 -15
- package/src/record/mesh-ssbo.ts +47 -36
- package/src/record/render-context.ts +136 -3
- package/src/record/shadow-pass.ts +83 -68
- package/src/record/skybox-post-pass.ts +20 -4
- package/src/record/typed-frame-graph.ts +1034 -43
- package/src/record/view-ubo.ts +72 -47
- package/src/reflection/filter.ts +81 -0
- package/src/reflection/gpu-table.ts +44 -0
- package/src/reflection/inspection.ts +67 -0
- package/src/reflection/projection.ts +476 -0
- package/src/reflection/record-owner.ts +1283 -0
- package/src/render-contract.ts +93 -10
- package/src/render-graph-primitives.ts +9 -4
- package/src/render-pipeline.ts +122 -2
- package/src/render-system-extract.ts +1041 -225
- package/src/render-system.ts +1310 -85
- package/src/renderer.ts +222 -0
- package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
- package/src/scene/probe-blend-record.ts +54 -0
- package/src/scene/probe-blend.ts +813 -0
- package/src/scene/render-scene-types.ts +0 -7
- package/src/scene/render-scene.ts +942 -171
- package/src/scene/visibility/bounds.ts +57 -0
- package/src/scene/visibility/budget.ts +40 -0
- package/src/scene/visibility/facet.ts +400 -0
- package/src/scene/visibility/gpu-frame-timing.ts +101 -0
- package/src/scene/visibility/gpu-lod.ts +119 -0
- package/src/scene/visibility/inspection.ts +313 -0
- package/src/scene/visibility/lod-selector.ts +84 -0
- package/src/scene/visibility/occlusion-confidence.ts +478 -0
- package/src/scene/visibility/occlusion-pass.ts +165 -0
- package/src/scene/visibility/occlusion-query-pool.ts +178 -0
- package/src/scene/visibility/occlusion-runtime.ts +672 -0
- package/src/scene/visibility/types.ts +50 -0
- package/src/shadow-atlas.ts +5 -5
- package/src/ssao-buffers.ts +9 -2
- package/src/ssr/admission.ts +451 -0
- package/src/ssr/composition.ts +73 -0
- package/src/ssr/errors.ts +76 -0
- package/src/ssr/identity.ts +12 -0
- package/src/systems/skin-palette-allocator.ts +1 -1
- package/src/targets/contracts.ts +182 -0
- package/src/targets/graph-projection.ts +169 -0
- package/src/targets/material-source.ts +143 -0
- package/src/targets/owner.ts +214 -0
- package/src/targets/physical.ts +18 -0
- package/src/targets/readback.ts +153 -0
- package/src/temporal/frame-coordinator.ts +26 -0
- package/src/temporal/frame.ts +14 -1
- package/src/temporal/view.ts +11 -0
- package/src/tilemap-chunk-extract-system.ts +4 -4
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
- package/src/typed-render-graph-primitives.ts +53 -3
- package/src/typed-shadow-passes.ts +46 -40
- package/src/volume/passes.ts +61 -58
- package/dist/.tsbuildinfo +0 -1
- package/dist/chunk-4XINDLAY.mjs.map +0 -1
- package/dist/chunk-CDTWTHZR.mjs.map +0 -1
- package/dist/chunk-M2MP4ZOU.mjs +0 -73
- package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
- package/dist/chunk-PCHBPYML.mjs.map +0 -1
- package/dist/chunk-TBQJOK2L.mjs.map +0 -1
- package/dist/chunk-VFPLTKCU.mjs.map +0 -1
|
@@ -11,7 +11,11 @@ import type {
|
|
|
11
11
|
RenderPipelineFrame,
|
|
12
12
|
RenderPipelineTopology,
|
|
13
13
|
} from '../render-pipeline';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
createRenderPipelineTarget,
|
|
16
|
+
type RenderPipelineTarget,
|
|
17
|
+
resolveOutputDither,
|
|
18
|
+
} from '../render-pipeline';
|
|
15
19
|
import {
|
|
16
20
|
addTypedBloomPasses,
|
|
17
21
|
addTypedCompositePostEffects,
|
|
@@ -134,7 +138,7 @@ function missingTemporalContributor(
|
|
|
134
138
|
return new SceneDataUnavailableError({
|
|
135
139
|
featureIdentity: 'forgeax::standard',
|
|
136
140
|
schema: 'forgeax::scene-data::temporal-v1',
|
|
137
|
-
lane: topology.lane.compute ?
|
|
141
|
+
lane: topology.lane.compute ? 'clustered' : 'cpu-webgl2',
|
|
138
142
|
reason: 'producer-missing',
|
|
139
143
|
missingContributorIds: [contributorId],
|
|
140
144
|
omittedMissingContributorCount: 0,
|
|
@@ -165,9 +169,13 @@ export function addStandardPost(
|
|
|
165
169
|
// left clear and the following Output Transform presents a black frame.
|
|
166
170
|
const bloomActive = hdr && topology.camera.bloom === 'on' && topology.camera.tonemap !== 'none';
|
|
167
171
|
const fxaa = !clearOnly && topology.camera.antialias === 'fxaa';
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
// All non-clear Standard frames use the graph-owned float scene target and
|
|
173
|
+
// the shared Output Transform, even when AA is disabled or the backend has
|
|
174
|
+
// no storage buffers. This keeps the final dither at one owner-level
|
|
175
|
+
// surface boundary instead of making no-AA/WebGL2 a silent bypass.
|
|
176
|
+
const linearLdr = !clearOnly && !hdr;
|
|
170
177
|
const rawOnly = !clearOnly && topology.surface.profile?.kind === 'raw-only';
|
|
178
|
+
const outputDither = resolveOutputDither(topology.config);
|
|
171
179
|
const motionBlur = !clearOnly && topology.temporal?.motionBlur === true;
|
|
172
180
|
const postEffects = clearOnly ? [] : (topology.config?.postEffects ?? []);
|
|
173
181
|
const rawOnlyPostInput =
|
|
@@ -312,7 +320,11 @@ export function addStandardPost(
|
|
|
312
320
|
domain: 'display-encoded',
|
|
313
321
|
});
|
|
314
322
|
if (!output.ok) return output;
|
|
315
|
-
|
|
323
|
+
// FXAA samples this display-encoded intermediate; leave dither to the
|
|
324
|
+
// final FXAA writer so the same pixel is not dithered twice.
|
|
325
|
+
const outputTransform = addTypedOutputTransformPass(context.graph, postInput, output.value, {
|
|
326
|
+
dither: false,
|
|
327
|
+
});
|
|
316
328
|
if (!outputTransform.ok) return outputTransform;
|
|
317
329
|
const aa = addTypedFullscreenPass(context.graph, {
|
|
318
330
|
name: 'fxaa',
|
|
@@ -326,13 +338,20 @@ export function addStandardPost(
|
|
|
326
338
|
context.graph,
|
|
327
339
|
postInput,
|
|
328
340
|
rawOnlyPostInput.value,
|
|
341
|
+
{
|
|
342
|
+
dither: outputDither && postEffects.length === 0,
|
|
343
|
+
},
|
|
329
344
|
);
|
|
330
345
|
if (!transformed.ok) return transformed;
|
|
331
346
|
} else if (rawOnly || linearLdr) {
|
|
332
|
-
const transformed = addTypedOutputTransformPass(context.graph, postInput, finalPresent
|
|
347
|
+
const transformed = addTypedOutputTransformPass(context.graph, postInput, finalPresent, {
|
|
348
|
+
dither: outputDither,
|
|
349
|
+
});
|
|
333
350
|
if (!transformed.ok) return transformed;
|
|
334
351
|
} else {
|
|
335
|
-
const outputTransform = addTypedOutputTransformPass(context.graph, postInput, finalPresent
|
|
352
|
+
const outputTransform = addTypedOutputTransformPass(context.graph, postInput, finalPresent, {
|
|
353
|
+
dither: outputDither,
|
|
354
|
+
});
|
|
336
355
|
if (!outputTransform.ok) return outputTransform;
|
|
337
356
|
}
|
|
338
357
|
}
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
export const STANDARD_PIPELINE_ID = 'forgeax::standard' as const;
|
|
2
2
|
export const STANDARD_LIGHT_COUNTS = [1, 32, 256] as const;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export {
|
|
4
|
+
CLUSTER_GRID_STRIDE_U32,
|
|
5
|
+
DEFAULT_CLUSTER_GRID,
|
|
6
|
+
LIGHT_INDEX_LIST_CAPACITY,
|
|
7
|
+
MAX_LIGHTS,
|
|
8
|
+
} from './standard-lighting/layout';
|
|
8
9
|
|
|
9
10
|
export type StandardLightCount = (typeof STANDARD_LIGHT_COUNTS)[number];
|
|
10
|
-
export type StandardLightingLane = 'direct' | 'clustered';
|
|
11
|
-
export type StandardFallbackLane = 'native' | 'cpu-webgl2';
|
|
12
11
|
export type StandardShadowMode = 'off' | 'hard' | 'filtered';
|
|
13
|
-
export type
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
| 'reinhard-extended';
|
|
22
|
-
export type StandardAntialias = 'none' | 'fxaa' | 'msaa';
|
|
12
|
+
export type StandardVolumetricFogQuality = 'low' | 'high';
|
|
13
|
+
|
|
14
|
+
export interface StandardVolumetricFogProfile {
|
|
15
|
+
readonly quality: StandardVolumetricFogQuality;
|
|
16
|
+
readonly depth: 48 | 64;
|
|
17
|
+
readonly tileSize: 4 | 16;
|
|
18
|
+
}
|
|
19
|
+
|
|
23
20
|
export const STANDARD_POST_STAGE_NAMES = [
|
|
24
21
|
'transparent-blend',
|
|
25
22
|
'bloom',
|
|
@@ -29,45 +26,28 @@ export const STANDARD_POST_STAGE_NAMES = [
|
|
|
29
26
|
'present',
|
|
30
27
|
] as const;
|
|
31
28
|
export type StandardPostStage = (typeof STANDARD_POST_STAGE_NAMES)[number];
|
|
32
|
-
export type StandardVolumetricFogQuality = 'low' | 'high';
|
|
33
|
-
|
|
34
|
-
export interface StandardVolumetricFogProfile {
|
|
35
|
-
readonly quality: StandardVolumetricFogQuality;
|
|
36
|
-
readonly depth: 48 | 64;
|
|
37
|
-
readonly tileSize: 4 | 16;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
29
|
export interface StandardProfile {
|
|
41
30
|
readonly pipelineId: typeof STANDARD_PIPELINE_ID;
|
|
42
31
|
readonly lightCount: StandardLightCount;
|
|
43
|
-
|
|
32
|
+
/** Graph topology selector; all local lights use the shared Cluster path. */
|
|
33
|
+
readonly renderPath: 'forward' | 'deferred';
|
|
44
34
|
readonly shadows: StandardShadowMode;
|
|
45
35
|
readonly pbr: boolean;
|
|
46
36
|
readonly ibl: boolean;
|
|
47
37
|
readonly ssao: boolean;
|
|
48
|
-
readonly bloom: boolean;
|
|
49
|
-
readonly tone: StandardTone;
|
|
50
|
-
readonly antialias: StandardAntialias;
|
|
51
|
-
readonly sky: boolean;
|
|
52
38
|
/** Renderer-owned 1080p volume profile; tile width/height remain surface-derived. */
|
|
53
39
|
readonly volumetricFog?: StandardVolumetricFogProfile | undefined;
|
|
54
|
-
readonly fallback: StandardFallbackLane;
|
|
55
40
|
readonly postStages: typeof STANDARD_POST_STAGE_NAMES;
|
|
56
41
|
}
|
|
57
42
|
|
|
58
43
|
export const DEFAULT_STANDARD_PROFILE: StandardProfile = Object.freeze({
|
|
59
44
|
pipelineId: STANDARD_PIPELINE_ID,
|
|
60
45
|
lightCount: 32,
|
|
61
|
-
|
|
46
|
+
renderPath: 'forward',
|
|
62
47
|
shadows: 'filtered',
|
|
63
48
|
pbr: true,
|
|
64
49
|
ibl: true,
|
|
65
50
|
ssao: false,
|
|
66
|
-
bloom: true,
|
|
67
|
-
tone: 'aces-filmic',
|
|
68
|
-
antialias: 'fxaa',
|
|
69
|
-
sky: true,
|
|
70
|
-
fallback: 'native',
|
|
71
51
|
postStages: STANDARD_POST_STAGE_NAMES,
|
|
72
52
|
});
|
|
73
53
|
|
|
@@ -76,13 +56,3 @@ export function resolveVolumetricFogProfile(
|
|
|
76
56
|
): StandardVolumetricFogProfile {
|
|
77
57
|
return profile.volumetricFog ?? { quality: 'high', depth: 64, tileSize: 4 };
|
|
78
58
|
}
|
|
79
|
-
|
|
80
|
-
export type StandardLane = StandardLightingLane | 'cpu-webgl2';
|
|
81
|
-
|
|
82
|
-
export function resolveStandardLane(
|
|
83
|
-
profile: Pick<StandardProfile, 'lighting'>,
|
|
84
|
-
capabilities: { readonly compute: boolean; readonly storageBuffer: boolean },
|
|
85
|
-
): StandardLane {
|
|
86
|
-
if (!capabilities.compute || !capabilities.storageBuffer) return 'cpu-webgl2';
|
|
87
|
-
return profile.lighting;
|
|
88
|
-
}
|
package/src/pipeline-builder.ts
CHANGED
|
@@ -122,6 +122,8 @@ export interface PipelineBuilderContext {
|
|
|
122
122
|
* tonemap field (M9 keeps the LDR shape; HDR variants are OOS-M9).
|
|
123
123
|
*/
|
|
124
124
|
readonly colorFormat: GPUTextureFormat;
|
|
125
|
+
/** Additional color targets for an MRT pass; the first target is colorFormat. */
|
|
126
|
+
readonly colorFormats?: readonly GPUTextureFormat[] | undefined;
|
|
125
127
|
/** Depth attachment format, or `undefined` for a color-only pass. */
|
|
126
128
|
readonly depthFormat: GPUTextureFormat | undefined;
|
|
127
129
|
/**
|
|
@@ -324,7 +326,8 @@ export function buildPipelineForMaterialShader(
|
|
|
324
326
|
// layout. The skinned variant additionally reads JOINTS_0 / WEIGHTS_0;
|
|
325
327
|
// both layouts come from the same geometry projection used by the main
|
|
326
328
|
// pass, so shadow rendering cannot silently reinterpret an 18F stream.
|
|
327
|
-
|
|
329
|
+
const attachmentFormats = ctx.colorFormats ?? colorFormatsForPassKind(passKind, ctx.colorFormat);
|
|
330
|
+
if (attachmentFormats.length === 0) {
|
|
328
331
|
// bug-20260619-csm RC-3 (AC-10): a material may supply a custom
|
|
329
332
|
// ShadowCaster pass shader that carries a fragment stage (e.g. an
|
|
330
333
|
// alpha-test cutout that calls `discard` and returns
|
|
@@ -399,7 +402,7 @@ export function buildPipelineForMaterialShader(
|
|
|
399
402
|
const forwardSpec: PipelineSpec = {
|
|
400
403
|
shader: { id, passKind, variantSet: undefined },
|
|
401
404
|
attachments: {
|
|
402
|
-
colorFormats:
|
|
405
|
+
colorFormats: attachmentFormats,
|
|
403
406
|
depthFormat: ctx.depthFormat,
|
|
404
407
|
sampleCount: (sampleCount === 4 ? 4 : 1) as 1 | 4,
|
|
405
408
|
},
|
package/src/pipeline-spec.ts
CHANGED
|
@@ -287,6 +287,80 @@ export function variantSetFromVertexLayoutProjection(
|
|
|
287
287
|
return ok(parts.join('+'));
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Derive the capability axes shared by every Standard PBR draw owner.
|
|
292
|
+
*
|
|
293
|
+
* The all-true key is the canonical empty key used by the shader manifest;
|
|
294
|
+
* every other capability pair stays explicit so a no-local-light frame on a
|
|
295
|
+
* device without storage buffers cannot accidentally select a storage-backed
|
|
296
|
+
* PSO. Vertex-color is supplied here because the empty-key rule is only valid
|
|
297
|
+
* when that geometry-owned axis is also true.
|
|
298
|
+
*/
|
|
299
|
+
export function standardCapabilityVariantSet(
|
|
300
|
+
clustered: boolean,
|
|
301
|
+
storageBuffer: boolean,
|
|
302
|
+
vertexColorAvailable: boolean,
|
|
303
|
+
): string {
|
|
304
|
+
if (clustered && storageBuffer && vertexColorAvailable) return '';
|
|
305
|
+
return `CLUSTER_FORWARD_AVAILABLE=${clustered}+STORAGE_BUFFER_AVAILABLE=${storageBuffer}`;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Project the frame-owned Standard topology onto its material variant axes.
|
|
310
|
+
*
|
|
311
|
+
* `StandardTopologyInputValue.kind` is the only runtime authority for the
|
|
312
|
+
* cluster axis: a frame with local lights must request the clustered artifact,
|
|
313
|
+
* while the no-local-light topology requests the direct artifact. Keeping
|
|
314
|
+
* this projection beside the canonical key builder prevents PBR, skin, and
|
|
315
|
+
* sprite-lit record owners from independently inferring the active lane from
|
|
316
|
+
* whichever bind group happened to be constructed first.
|
|
317
|
+
*/
|
|
318
|
+
export function standardTopologyVariantSet(
|
|
319
|
+
topology: { readonly kind: 'no-local-lights' | 'clustered' } | undefined,
|
|
320
|
+
storageBuffer: boolean,
|
|
321
|
+
vertexColorAvailable: boolean,
|
|
322
|
+
probeBlendAvailable = false,
|
|
323
|
+
): string {
|
|
324
|
+
const capabilityVariantSet = standardCapabilityVariantSet(
|
|
325
|
+
topology?.kind === 'clustered',
|
|
326
|
+
storageBuffer,
|
|
327
|
+
vertexColorAvailable,
|
|
328
|
+
);
|
|
329
|
+
if (!probeBlendAvailable || !storageBuffer) return capabilityVariantSet;
|
|
330
|
+
// The canonical empty key cannot carry the clustered=true fact through
|
|
331
|
+
// resolveMaterialShaderVariantSet (an omitted cluster axis means false).
|
|
332
|
+
// Expand that base before adding the object-level Probe ABI axis so shader,
|
|
333
|
+
// group(3) bind group, and pipeline layout remain one exact variant.
|
|
334
|
+
const explicitCapabilityVariantSet =
|
|
335
|
+
capabilityVariantSet === ''
|
|
336
|
+
? 'CLUSTER_FORWARD_AVAILABLE=true+STORAGE_BUFFER_AVAILABLE=true'
|
|
337
|
+
: capabilityVariantSet;
|
|
338
|
+
return `${explicitCapabilityVariantSet}+PROBE_BLEND_AVAILABLE=true`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Keep a clustered frame fail-closed when its unified group(2) resource is
|
|
343
|
+
* unavailable. A missing group is not evidence that the frame is direct; it
|
|
344
|
+
* is an invalid prepared resource state.
|
|
345
|
+
*/
|
|
346
|
+
export function standardTopologyBindGroupReady(
|
|
347
|
+
topology: { readonly kind: 'no-local-lights' | 'clustered' } | undefined,
|
|
348
|
+
clusterBindGroup: unknown,
|
|
349
|
+
): boolean {
|
|
350
|
+
return (
|
|
351
|
+
topology?.kind !== 'clustered' || (clusterBindGroup !== null && clusterBindGroup !== undefined)
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** Derive the storage axis for Standard-compatible unlit material draws. */
|
|
356
|
+
export function standardStorageVariantSet(
|
|
357
|
+
storageBuffer: boolean,
|
|
358
|
+
vertexColorAvailable: boolean,
|
|
359
|
+
): string {
|
|
360
|
+
if (storageBuffer && vertexColorAvailable) return '';
|
|
361
|
+
return `STORAGE_BUFFER_AVAILABLE=${storageBuffer}+VERTEX_COLOR_AVAILABLE=${vertexColorAvailable}`;
|
|
362
|
+
}
|
|
363
|
+
|
|
290
364
|
/**
|
|
291
365
|
* Build a `GPURenderPipelineDescriptor` from a PipelineSpec + shader modules.
|
|
292
366
|
*
|
|
@@ -925,14 +999,14 @@ const TRI_GEOMETRY_PBR = {
|
|
|
925
999
|
shaderUvSetCount: 8,
|
|
926
1000
|
};
|
|
927
1001
|
|
|
928
|
-
// M6 fix-up:
|
|
929
|
-
// boot-time variantSet computed at createRenderer.ts step 1b when
|
|
930
|
-
//
|
|
931
|
-
// surface). The
|
|
1002
|
+
// M6 fix-up: non-clustered boot-variant key string for the standard PBR shader.
|
|
1003
|
+
// Mirrors the boot-time variantSet computed at createRenderer.ts step 1b when
|
|
1004
|
+
// clustered lighting is not yet admitted and `storageBufferCapable=true` (the
|
|
1005
|
+
// surface). The default record path requests this exact string at every
|
|
932
1006
|
// `getMaterialShaderPipeline` call site, so seeding the table with these
|
|
933
|
-
// variants keeps the
|
|
1007
|
+
// variants keeps the default cache lookup hot from frame 1 instead of
|
|
934
1008
|
// skip-drawing the first ~1 frames while the async compile resolves.
|
|
935
|
-
const
|
|
1009
|
+
const STANDARD_BOOT_VARIANT_SET = standardCapabilityVariantSet(false, true, false);
|
|
936
1010
|
|
|
937
1011
|
/**
|
|
938
1012
|
* Build the boot-time pre-warm table: 15 standard PipelineSpec variants.
|
|
@@ -944,22 +1018,22 @@ const URP_PBR_VARIANT_SET = 'CLUSTER_FORWARD_AVAILABLE=false+STORAGE_BUFFER_AVAI
|
|
|
944
1018
|
*
|
|
945
1019
|
* Matrix:
|
|
946
1020
|
* - 8 base material variants — {unlit, standard-pbr} x {LDR, HDR} x {S1, S4}
|
|
947
|
-
* - 4
|
|
948
|
-
* x {LDR, HDR} x {S1, S4};
|
|
1021
|
+
* - 4 non-clustered standard-pbr — standard-pbr (variantSet=STANDARD_BOOT_VARIANT_SET)
|
|
1022
|
+
* x {LDR, HDR} x {S1, S4}; the default record path requests these specs by
|
|
949
1023
|
* `getMaterialShaderPipeline` keying off `cacheKeyOf` so the boot-time
|
|
950
1024
|
* prewarm seeds `materialShaderPipelineCache` and avoids a 1-frame
|
|
951
|
-
* async-compile skip-draw (M6 fix-up; see render-system-record.ts
|
|
1025
|
+
* async-compile skip-draw (M6 fix-up; see render-system-record.ts)
|
|
952
1026
|
* - 3 fullscreen-post — tonemap (LDR S1) + skybox (HDR S1, HDR S4)
|
|
953
1027
|
*
|
|
954
|
-
* Total: 15. The
|
|
955
|
-
* - unlit
|
|
1028
|
+
* Total: 15. The non-clustered variant is PBR-only because:
|
|
1029
|
+
* - unlit record path passes `variantSet=undefined` (the no-variant
|
|
956
1030
|
* boot-default entries already cover it; createRenderer.ts §unlitRsp)
|
|
957
1031
|
* - sprite goes through `getMaterialShaderPipeline('forgeax::sprite', ...)`
|
|
958
1032
|
* lazily at first transparent-LDR-split draw — no boot-time pre-warm.
|
|
959
|
-
* -
|
|
1033
|
+
* - clustered variant (`variantSet=''` or compound `=true` form) is registered
|
|
960
1034
|
* lazily when the clustered Standard profile activates, not at boot — adding clustered
|
|
961
1035
|
* prewarm here would build PSOs against the URP layout (the boot-time
|
|
962
|
-
* `pbrModule` is the
|
|
1036
|
+
* `pbrModule` is the non-clustered variant before a frame admits local lights)
|
|
963
1037
|
*
|
|
964
1038
|
* `ldrViewFormat` parameterises the LDR color attachment format. Callers
|
|
965
1039
|
* pass the runtime-resolved swap-chain view format (Channel 2 typically
|
|
@@ -1074,12 +1148,12 @@ export function buildSpecConstTable(
|
|
|
1074
1148
|
renderState: undefined,
|
|
1075
1149
|
},
|
|
1076
1150
|
|
|
1077
|
-
// ── M6 fix-up:
|
|
1078
|
-
//
|
|
1079
|
-
// `variantSet=
|
|
1151
|
+
// ── M6 fix-up: non-clustered standard-pbr prewarm ─────────────────────────
|
|
1152
|
+
// The default record path (`getMaterialShaderPipeline`) requests
|
|
1153
|
+
// `variantSet=STANDARD_BOOT_VARIANT_SET` for standard-shading entities; pre-M6
|
|
1080
1154
|
// the silent `selectStandardFallbackPipeline` shim served the no-variant
|
|
1081
1155
|
// boot prewarm during the 1-frame async-compile warmup. With M6's
|
|
1082
|
-
// explicit-failure surface, those
|
|
1156
|
+
// explicit-failure surface, those requests must hit the boot prewarm
|
|
1083
1157
|
// by their own variantSet — these 4 entries close that gap.
|
|
1084
1158
|
|
|
1085
1159
|
// standard PBR URP LDR S1
|
|
@@ -1087,7 +1161,7 @@ export function buildSpecConstTable(
|
|
|
1087
1161
|
shader: {
|
|
1088
1162
|
id: 'forgeax::default-standard-pbr',
|
|
1089
1163
|
passKind: 'forward',
|
|
1090
|
-
variantSet:
|
|
1164
|
+
variantSet: STANDARD_BOOT_VARIANT_SET,
|
|
1091
1165
|
},
|
|
1092
1166
|
attachments: TRI_ATTACHMENTS_LDR_S1,
|
|
1093
1167
|
geometry: TRI_GEOMETRY_PBR,
|
|
@@ -1098,7 +1172,7 @@ export function buildSpecConstTable(
|
|
|
1098
1172
|
shader: {
|
|
1099
1173
|
id: 'forgeax::default-standard-pbr',
|
|
1100
1174
|
passKind: 'forward',
|
|
1101
|
-
variantSet:
|
|
1175
|
+
variantSet: STANDARD_BOOT_VARIANT_SET,
|
|
1102
1176
|
},
|
|
1103
1177
|
attachments: TRI_ATTACHMENTS_LDR_S4,
|
|
1104
1178
|
geometry: TRI_GEOMETRY_PBR,
|
|
@@ -1109,7 +1183,7 @@ export function buildSpecConstTable(
|
|
|
1109
1183
|
shader: {
|
|
1110
1184
|
id: 'forgeax::default-standard-pbr',
|
|
1111
1185
|
passKind: 'forward',
|
|
1112
|
-
variantSet:
|
|
1186
|
+
variantSet: STANDARD_BOOT_VARIANT_SET,
|
|
1113
1187
|
},
|
|
1114
1188
|
attachments: TRI_ATTACHMENTS_HDR_S1,
|
|
1115
1189
|
geometry: TRI_GEOMETRY_PBR,
|
|
@@ -1120,7 +1194,7 @@ export function buildSpecConstTable(
|
|
|
1120
1194
|
shader: {
|
|
1121
1195
|
id: 'forgeax::default-standard-pbr',
|
|
1122
1196
|
passKind: 'forward',
|
|
1123
|
-
variantSet:
|
|
1197
|
+
variantSet: STANDARD_BOOT_VARIANT_SET,
|
|
1124
1198
|
},
|
|
1125
1199
|
attachments: TRI_ATTACHMENTS_HDR_S4,
|
|
1126
1200
|
geometry: TRI_GEOMETRY_PBR,
|
package/src/plugin.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { Camera } from './components/camera';
|
|
|
5
5
|
import { DirectionalLight } from './components/directional-light';
|
|
6
6
|
import { Instances } from './components/instances';
|
|
7
7
|
import { Layer } from './components/layer';
|
|
8
|
+
import { LightProbe } from './components/light-probe';
|
|
8
9
|
import { Lines } from './components/lines';
|
|
9
10
|
import { MeshFilter } from './components/mesh-filter';
|
|
10
11
|
import { MeshRenderer } from './components/mesh-renderer';
|
|
@@ -12,6 +13,7 @@ import { PointLight } from './components/point-light';
|
|
|
12
13
|
import { PointLightShadow } from './components/point-light-shadow';
|
|
13
14
|
import { Points } from './components/points';
|
|
14
15
|
import { PostProcessParams } from './components/post-process-params';
|
|
16
|
+
import { RectAreaLight } from './components/rect-area-light';
|
|
15
17
|
import { SceneInstance } from './components/scene-instance';
|
|
16
18
|
import { SkyboxBackground } from './components/skybox-background';
|
|
17
19
|
import { Skylight } from './components/skylight';
|
|
@@ -30,6 +32,7 @@ const RENDER_COMPONENTS: readonly Component[] = [
|
|
|
30
32
|
DirectionalLight,
|
|
31
33
|
Instances,
|
|
32
34
|
Layer,
|
|
35
|
+
LightProbe,
|
|
33
36
|
MeshFilter,
|
|
34
37
|
MeshRenderer,
|
|
35
38
|
PointLight,
|
|
@@ -37,6 +40,7 @@ const RENDER_COMPONENTS: readonly Component[] = [
|
|
|
37
40
|
Points,
|
|
38
41
|
Lines,
|
|
39
42
|
PostProcessParams,
|
|
43
|
+
RectAreaLight,
|
|
40
44
|
SceneInstance,
|
|
41
45
|
SkyboxBackground,
|
|
42
46
|
Skylight,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { PointShadowSnapshot } from './render-system-extract';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Detached point-shadow budget facts from one completed extract/record frame.
|
|
5
|
+
*
|
|
6
|
+
* `requested` is the number of PointLight + PointLightShadow pairs. The
|
|
7
|
+
* renderer owns the bounded cube-array atlas, so `admitted`, `shadowed`, and
|
|
8
|
+
* `shadowAtlasOccupancy` are all derived from the layer sentinel emitted by
|
|
9
|
+
* the same extract owner. No consumer needs to maintain a second budget
|
|
10
|
+
* ledger.
|
|
11
|
+
*/
|
|
12
|
+
export interface PointShadowInspection {
|
|
13
|
+
readonly status: 'inactive' | 'ready' | 'over-budget';
|
|
14
|
+
readonly requested: number;
|
|
15
|
+
readonly admitted: number;
|
|
16
|
+
readonly shadowed: number;
|
|
17
|
+
readonly shadowAtlasOccupancy: number;
|
|
18
|
+
readonly shadowAtlasCapacity: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Project point-shadow snapshots to the public, JSON-safe inspection shape. */
|
|
22
|
+
export function inspectPointShadow(
|
|
23
|
+
snapshots: readonly PointShadowSnapshot[],
|
|
24
|
+
shadowAtlasCapacity: number,
|
|
25
|
+
): PointShadowInspection {
|
|
26
|
+
const requested = snapshots.length;
|
|
27
|
+
const admitted = snapshots.reduce(
|
|
28
|
+
(count, snapshot) =>
|
|
29
|
+
snapshot.shadowAtlasLayer >= 0 && snapshot.shadowAtlasLayer < shadowAtlasCapacity
|
|
30
|
+
? count + 1
|
|
31
|
+
: count,
|
|
32
|
+
0,
|
|
33
|
+
);
|
|
34
|
+
// Never publish a misleading `ready` state when any requested shadow owns
|
|
35
|
+
// no atlas layer. The extract sentinel is the single admission projection;
|
|
36
|
+
// a partial or all-sentinel frame is therefore a failed/over-budget
|
|
37
|
+
// admission, not an active shadow path with incomplete output.
|
|
38
|
+
const status =
|
|
39
|
+
requested === 0
|
|
40
|
+
? ('inactive' as const)
|
|
41
|
+
: requested > shadowAtlasCapacity || admitted !== requested
|
|
42
|
+
? ('over-budget' as const)
|
|
43
|
+
: ('ready' as const);
|
|
44
|
+
return Object.freeze({
|
|
45
|
+
status,
|
|
46
|
+
requested,
|
|
47
|
+
admitted,
|
|
48
|
+
// A point shadow only samples an atlas after it owns an atlas layer. Keep
|
|
49
|
+
// these names explicit for AI diagnostics while deriving both from the
|
|
50
|
+
// one layer projection above.
|
|
51
|
+
shadowed: admitted,
|
|
52
|
+
shadowAtlasOccupancy: admitted,
|
|
53
|
+
shadowAtlasCapacity,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { RhiCaps, RhiDevice } from '@forgeax/engine-rhi';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { deriveExtendedLightingCapability } from '../extended-lighting/resources';
|
|
4
|
+
|
|
5
|
+
const device = {
|
|
6
|
+
caps: {
|
|
7
|
+
backendKind: 'null',
|
|
8
|
+
compute: true,
|
|
9
|
+
storageBuffer: true,
|
|
10
|
+
storageTexture: true,
|
|
11
|
+
rgba16floatRenderable: true,
|
|
12
|
+
samplerAliasing: true,
|
|
13
|
+
} as RhiCaps,
|
|
14
|
+
limits: {
|
|
15
|
+
maxSampledTexturesPerShaderStage: 20,
|
|
16
|
+
maxTextureDimension2D: 4096,
|
|
17
|
+
maxTextureArrayLayers: 32,
|
|
18
|
+
maxUniformBuffersPerShaderStage: 12,
|
|
19
|
+
},
|
|
20
|
+
} as unknown as RhiDevice;
|
|
21
|
+
|
|
22
|
+
describe('extended lighting capability admission', () => {
|
|
23
|
+
it('derives admission from real format, filter, array, and uniform facts', () => {
|
|
24
|
+
expect(deriveExtendedLightingCapability(device)).toEqual({
|
|
25
|
+
admitted: true,
|
|
26
|
+
topology: 'extendedLighting',
|
|
27
|
+
reason: undefined,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('rejects a device whose array or uniform limit cannot hold the contract', () => {
|
|
32
|
+
const limited = {
|
|
33
|
+
...device,
|
|
34
|
+
limits: { ...device.limits, maxTextureArrayLayers: 16, maxUniformBuffersPerShaderStage: 0 },
|
|
35
|
+
} as RhiDevice;
|
|
36
|
+
|
|
37
|
+
expect(deriveExtendedLightingCapability(limited)).toMatchObject({
|
|
38
|
+
admitted: false,
|
|
39
|
+
topology: 'extendedLighting',
|
|
40
|
+
reason: expect.stringContaining('maxTextureArrayLayers'),
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('rejects the topology when the sampled-texture limit is below the shader contract', () => {
|
|
45
|
+
const limited = {
|
|
46
|
+
...device,
|
|
47
|
+
limits: { ...device.limits, maxSampledTexturesPerShaderStage: 16 },
|
|
48
|
+
} as RhiDevice;
|
|
49
|
+
|
|
50
|
+
expect(deriveExtendedLightingCapability(limited)).toEqual({
|
|
51
|
+
admitted: false,
|
|
52
|
+
topology: 'extendedLighting',
|
|
53
|
+
reason: 'maxSampledTexturesPerShaderStage 16 < 20',
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// @forgeax/engine-render - DeviceScope-owned RectArea LTC resources.
|
|
2
|
+
|
|
3
|
+
import type { Result, RhiDevice, RhiError, Texture } from '@forgeax/engine-rhi';
|
|
4
|
+
import { LTC_TABLE_HEIGHT, LTC_TABLE_WIDTH, LTC_TABLES } from '@forgeax/engine-shader';
|
|
5
|
+
import { err, ok } from '@forgeax/engine-types';
|
|
6
|
+
import { type DeviceScope, LifecycleTransaction } from '../../device/device-scope';
|
|
7
|
+
import {
|
|
8
|
+
GPU_TEXTURE_USAGE_COPY_DST,
|
|
9
|
+
GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
10
|
+
} from '../../gpu-texture-usage';
|
|
11
|
+
import { deriveExtendedLightingCapability, EXTENDED_LIGHTING_TOPOLOGY } from './resources';
|
|
12
|
+
|
|
13
|
+
export interface LtcResourcePlanInput {
|
|
14
|
+
readonly scope: DeviceScope;
|
|
15
|
+
readonly ltcAvailable: boolean;
|
|
16
|
+
readonly residentGeneration?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface LtcResourcePlan {
|
|
20
|
+
readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;
|
|
21
|
+
readonly generation: number;
|
|
22
|
+
readonly rectAdmission: 'admitted' | 'omitted';
|
|
23
|
+
readonly tableCount: number;
|
|
24
|
+
readonly uploadCount: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface LtcResourceCandidate {
|
|
28
|
+
readonly topology: typeof EXTENDED_LIGHTING_TOPOLOGY;
|
|
29
|
+
readonly generation: number;
|
|
30
|
+
readonly scope: DeviceScope;
|
|
31
|
+
readonly lambertTexture: Texture;
|
|
32
|
+
readonly ggxTexture: Texture;
|
|
33
|
+
readonly tableCount: 2;
|
|
34
|
+
readonly uploadCount: 2;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function deriveLtcResourcePlan(input: LtcResourcePlanInput): LtcResourcePlan {
|
|
38
|
+
const admitted = input.ltcAvailable;
|
|
39
|
+
return {
|
|
40
|
+
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
41
|
+
generation: input.scope.generation,
|
|
42
|
+
rectAdmission: admitted ? 'admitted' : 'omitted',
|
|
43
|
+
tableCount: admitted ? 2 : 0,
|
|
44
|
+
uploadCount: admitted && input.residentGeneration !== input.scope.generation ? 2 : 0,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function failure(expected: string, actual: string): Result<never, RhiError> {
|
|
49
|
+
return err({
|
|
50
|
+
code: 'webgpu-runtime-error',
|
|
51
|
+
expected,
|
|
52
|
+
hint: 'inspect device capabilities and retry the extendedLighting candidate',
|
|
53
|
+
detail: { error: { code: 'ltc-resource', message: actual } },
|
|
54
|
+
} as RhiError);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function textureBytes(table: Uint16Array): Uint8Array {
|
|
58
|
+
return new Uint8Array(table.buffer, table.byteOffset, table.byteLength);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Create both tracked tables atomically; unavailable LTC only omits Rect. */
|
|
62
|
+
export async function createLtcResourceCandidate(input: {
|
|
63
|
+
readonly device: RhiDevice | undefined;
|
|
64
|
+
readonly scope: DeviceScope;
|
|
65
|
+
}): Promise<Result<LtcResourceCandidate | undefined, RhiError>> {
|
|
66
|
+
if (input.device === undefined) return ok(undefined);
|
|
67
|
+
if (!deriveExtendedLightingCapability(input.device).admitted) return ok(undefined);
|
|
68
|
+
const device = input.device;
|
|
69
|
+
|
|
70
|
+
const transaction = new LifecycleTransaction(input.scope);
|
|
71
|
+
let lambertTexture: Texture | undefined;
|
|
72
|
+
let ggxTexture: Texture | undefined;
|
|
73
|
+
const createTable = (label: string, table: Uint16Array): Texture => {
|
|
74
|
+
const texture = device.createTexture({
|
|
75
|
+
label,
|
|
76
|
+
size: { width: LTC_TABLE_WIDTH, height: LTC_TABLE_HEIGHT, depthOrArrayLayers: 1 },
|
|
77
|
+
mipLevelCount: 1,
|
|
78
|
+
sampleCount: 1,
|
|
79
|
+
dimension: '2d',
|
|
80
|
+
format: 'rgba16float',
|
|
81
|
+
usage: GPU_TEXTURE_USAGE_COPY_DST | GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
82
|
+
viewFormats: [],
|
|
83
|
+
textureBindingViewDimension: undefined,
|
|
84
|
+
});
|
|
85
|
+
if (texture === undefined || !texture.ok) {
|
|
86
|
+
throw texture?.error ?? new Error('LTC texture creation returned no result');
|
|
87
|
+
}
|
|
88
|
+
const write = device.queue.writeTexture(
|
|
89
|
+
{ texture: texture.value, mipLevel: 0, origin: { x: 0, y: 0, z: 0 } },
|
|
90
|
+
textureBytes(table),
|
|
91
|
+
{ offset: 0, bytesPerRow: LTC_TABLE_WIDTH * 8, rowsPerImage: LTC_TABLE_HEIGHT },
|
|
92
|
+
{ width: LTC_TABLE_WIDTH, height: LTC_TABLE_HEIGHT, depthOrArrayLayers: 1 },
|
|
93
|
+
);
|
|
94
|
+
if (!write.ok) throw write.error;
|
|
95
|
+
return texture.value;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
transaction.add({
|
|
99
|
+
kind: 'texture',
|
|
100
|
+
create: () => {
|
|
101
|
+
lambertTexture = createTable('extended-lighting-ltc-lambert', LTC_TABLES.lambert);
|
|
102
|
+
return lambertTexture;
|
|
103
|
+
},
|
|
104
|
+
cleanup: (value) => {
|
|
105
|
+
const destroyed = input.device?.destroyTexture(value);
|
|
106
|
+
if (destroyed !== undefined && !destroyed.ok) throw destroyed.error;
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
transaction.add({
|
|
110
|
+
kind: 'texture',
|
|
111
|
+
create: () => {
|
|
112
|
+
ggxTexture = createTable('extended-lighting-ltc-ggx', LTC_TABLES.ggx);
|
|
113
|
+
return ggxTexture;
|
|
114
|
+
},
|
|
115
|
+
cleanup: (value) => {
|
|
116
|
+
const destroyed = input.device?.destroyTexture(value);
|
|
117
|
+
if (destroyed !== undefined && !destroyed.ok) throw destroyed.error;
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const committed = await transaction.commit();
|
|
122
|
+
if (!committed.ok)
|
|
123
|
+
return failure(committed.error.primary.expected, committed.error.primary.message);
|
|
124
|
+
if (lambertTexture === undefined || ggxTexture === undefined) {
|
|
125
|
+
return failure('two LTC textures', 'the transaction committed without both tables');
|
|
126
|
+
}
|
|
127
|
+
return ok({
|
|
128
|
+
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
129
|
+
generation: input.scope.generation,
|
|
130
|
+
scope: input.scope,
|
|
131
|
+
lambertTexture,
|
|
132
|
+
ggxTexture,
|
|
133
|
+
tableCount: 2,
|
|
134
|
+
uploadCount: 2,
|
|
135
|
+
});
|
|
136
|
+
}
|