@forgeax/engine-render 0.1.20 → 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 +21 -18
- 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-4XINDLAY.mjs → chunk-5YADUCA7.mjs} +1552 -1361
- package/dist/chunk-5YADUCA7.mjs.map +1 -0
- package/dist/{chunk-TBQJOK2L.mjs → chunk-6OPXDQ2E.mjs} +364 -51
- package/dist/chunk-6OPXDQ2E.mjs.map +1 -0
- package/dist/{chunk-M2MP4ZOU.mjs → chunk-BXBQQKFQ.mjs} +3 -9
- package/dist/chunk-BXBQQKFQ.mjs.map +1 -0
- package/dist/{chunk-CDTWTHZR.mjs → chunk-FS2KNUQH.mjs} +548 -6
- 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/construct-renderer.mjs +5826 -1003
- package/dist/construct-renderer.mjs.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 +141 -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/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 +28 -3
- 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 +10 -1
- 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 +14 -4
- 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-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 +27 -32
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +28 -14
- 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 +10 -4
- 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 +8 -3
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +22 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +43 -2
- 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 +72 -4
- 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 +49 -7
- 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 +42 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +58 -17
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +17 -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/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/index.mjs +3 -3
- package/dist/typed-render-graph-primitives.d.ts +1 -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 +2 -2
- 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 +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__/material-observation.integration.test.ts +101 -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__/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 +18 -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 +48 -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 +132 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +11 -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 -38
- 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/assembly/device-feature-admission.ts +73 -0
- package/src/assembly/directional-shadow-inspection.ts +122 -0
- package/src/assembly/factory.ts +877 -286
- 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 +81 -7
- package/src/components/reflection-probe.ts +49 -0
- package/src/environment/frame.ts +6 -24
- package/src/environment/lifecycle.ts +12 -0
- package/src/errors/render.ts +286 -142
- 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/hdrp-buffers.ts +165 -59
- package/src/ibl/IblPipelineCache.ts +11 -0
- package/src/ibl/kernel-cache.ts +88 -0
- package/src/index.ts +148 -0
- package/src/inspection-types.ts +56 -0
- package/src/instances-derived-bounds.ts +171 -0
- package/src/light-buffer-layout.ts +20 -5
- package/src/mesh-material-bindings.ts +132 -0
- package/src/pbr-pipeline.ts +106 -17
- package/src/pipeline/standard-forward-lane.ts +46 -16
- 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 +122 -193
- package/src/pipeline/standard-post.ts +26 -7
- package/src/pipeline/standard-profile.ts +17 -47
- 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 +367 -427
- package/src/record/frame-snapshot.ts +35 -27
- package/src/record/frame-targets.ts +17 -0
- package/src/record/frame.ts +261 -74
- 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 +21 -12
- package/src/record/main-pass-geometry.ts +120 -80
- package/src/record/main-pass-material.ts +95 -9
- package/src/record/main-pass-sprite-draws.ts +54 -25
- package/src/record/main-pass.ts +71 -15
- package/src/record/render-context.ts +72 -0
- package/src/record/shadow-pass.ts +17 -28
- package/src/record/skybox-post-pass.ts +20 -4
- package/src/record/typed-frame-graph.ts +893 -44
- 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 +76 -5
- package/src/render-graph-primitives.ts +9 -4
- package/src/render-pipeline.ts +117 -2
- package/src/render-system-extract.ts +557 -100
- package/src/render-system.ts +1095 -66
- package/src/renderer.ts +222 -0
- package/src/scene/render-scene.ts +115 -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/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
- package/src/typed-render-graph-primitives.ts +5 -3
- package/src/typed-shadow-passes.ts +46 -40
- package/src/volume/passes.ts +15 -9
- package/dist/chunk-4XINDLAY.mjs.map +0 -1
- package/dist/chunk-CDTWTHZR.mjs.map +0 -1
- package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
- package/dist/chunk-TBQJOK2L.mjs.map +0 -1
package/src/errors/render.ts
CHANGED
|
@@ -138,49 +138,33 @@ export class TemporalFrameSubmitError extends Error {
|
|
|
138
138
|
/**
|
|
139
139
|
* Detail for `RuntimeErrorCode 'shadow-invalid-config'`.
|
|
140
140
|
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* AI users access `.detail.field` / `.detail.value` / `.detail.min` /
|
|
144
|
-
* `.detail.max` via property access — no string parsing.
|
|
145
|
-
*
|
|
146
|
-
* `max` is `undefined` for lower-bound-only validations (e.g. mapSize < 1).
|
|
147
|
-
* feat-20260613-csm: max added for upper-bound cascade validations
|
|
148
|
-
* (cascadeCount max=4, splitLambda max=1, cascadeBlend max=0.5).
|
|
141
|
+
* The four fields are the only recovery surface: AI users read the invalid
|
|
142
|
+
* field, actual value, structured bound, and reason without parsing prose.
|
|
149
143
|
*/
|
|
144
|
+
export type ShadowInvalidConfigBound =
|
|
145
|
+
| { readonly kind: 'range'; readonly min: number; readonly max: number }
|
|
146
|
+
| { readonly kind: 'lower-bound'; readonly operator: '>' | '>='; readonly value: number }
|
|
147
|
+
| { readonly kind: 'allowed-values'; readonly values: readonly number[] };
|
|
148
|
+
|
|
150
149
|
export interface ShadowInvalidConfigDetail {
|
|
151
150
|
readonly field: string;
|
|
152
|
-
readonly
|
|
153
|
-
readonly
|
|
154
|
-
readonly
|
|
151
|
+
readonly actual: number;
|
|
152
|
+
readonly bound: ShadowInvalidConfigBound;
|
|
153
|
+
readonly reason: string;
|
|
155
154
|
}
|
|
156
155
|
|
|
157
156
|
/**
|
|
158
157
|
* Structured error for shadow component config validation failures.
|
|
159
158
|
*
|
|
160
|
-
* Emitted by
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* `RuntimeErrorCode` only needs one branch (charter P4 — closed-union SSOT).
|
|
165
|
-
* Four-field surface per AGENTS.md error model:
|
|
159
|
+
* Emitted by Directional, Point, and Spot shadow validation. All three
|
|
160
|
+
* component owners share this error class so `switch (err.code)` on
|
|
161
|
+
* `RuntimeErrorCode` needs one branch (charter P4 — closed-union SSOT).
|
|
162
|
+
* Four-field surface:
|
|
166
163
|
* - `.code = 'shadow-invalid-config'` (closed RuntimeErrorCode)
|
|
167
164
|
* - `.expected` — expected-state description (programmatic predicate form)
|
|
168
165
|
* - `.hint` — actionable recovery guidance (imperative; AI users paste into
|
|
169
|
-
* spawn calls).
|
|
170
|
-
*
|
|
171
|
-
* "<comparator> min".
|
|
172
|
-
* - `.detail = { field, value, min, max? }` — structured values (charter P4)
|
|
173
|
-
*
|
|
174
|
-
* 4th constructor parameter is a union over the two range shapes:
|
|
175
|
-
* - `number` — `max` for a closed `[min, max]` range (CSM cascadeCount /
|
|
176
|
-
* splitLambda / cascadeBlend). hint uses "in [min, max]"; integer-typed
|
|
177
|
-
* fields get "integer in [min, max]".
|
|
178
|
-
* - `'>' | '>='` — comparator for an open lower-bound predicate. `'>'` is
|
|
179
|
-
* used when `min` carries dynamic context (e.g. `farPlane > nearPlane` —
|
|
180
|
-
* the surfaced hint reads "must be > nearPlane" so AI users setting
|
|
181
|
-
* farPlane=nearPlane don't re-fail the spawn loop with the wrong cue).
|
|
182
|
-
* - `undefined` — defaults to `'>='`. Callsites for mapSize < 1 validation
|
|
183
|
-
* stay backward-compatible (3-arg form).
|
|
166
|
+
* spawn calls).
|
|
167
|
+
* - `.detail = { field, actual, bound, reason }` — structured values.
|
|
184
168
|
*/
|
|
185
169
|
export class ShadowInvalidConfigError extends Error {
|
|
186
170
|
readonly code = 'shadow-invalid-config' as const;
|
|
@@ -188,35 +172,53 @@ export class ShadowInvalidConfigError extends Error {
|
|
|
188
172
|
readonly hint: string;
|
|
189
173
|
readonly detail: ShadowInvalidConfigDetail;
|
|
190
174
|
|
|
191
|
-
constructor(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const expected =
|
|
210
|
-
|
|
211
|
-
super(
|
|
212
|
-
max !== undefined
|
|
213
|
-
? `shadow component .${field} must be in [${min}, ${max}], got ${value}`
|
|
214
|
-
: `shadow component .${field} must be ${comparator} ${min}, got ${value}`,
|
|
215
|
-
);
|
|
175
|
+
constructor(
|
|
176
|
+
field: string,
|
|
177
|
+
actual: number,
|
|
178
|
+
minOrBound: number | ShadowInvalidConfigBound,
|
|
179
|
+
maxOrComparator?: number | '>' | '>=',
|
|
180
|
+
reason?: string,
|
|
181
|
+
) {
|
|
182
|
+
const bound: ShadowInvalidConfigBound =
|
|
183
|
+
typeof minOrBound === 'number'
|
|
184
|
+
? typeof maxOrComparator === 'number'
|
|
185
|
+
? { kind: 'range', min: minOrBound, max: maxOrComparator }
|
|
186
|
+
: {
|
|
187
|
+
kind: 'lower-bound',
|
|
188
|
+
operator: maxOrComparator === '>' ? '>' : '>=',
|
|
189
|
+
value: minOrBound,
|
|
190
|
+
}
|
|
191
|
+
: minOrBound;
|
|
192
|
+
const resolvedReason = reason ?? shadowBoundReason(bound);
|
|
193
|
+
const expected = shadowBoundExpected(field, bound);
|
|
194
|
+
const hint = `set ${field} to ${resolvedReason}; got ${actual}`;
|
|
195
|
+
super(`shadow component .${field} is invalid: ${resolvedReason}; got ${actual}`);
|
|
216
196
|
this.name = 'ShadowInvalidConfigError';
|
|
217
197
|
this.hint = hint;
|
|
218
198
|
this.expected = expected;
|
|
219
|
-
this.detail = { field,
|
|
199
|
+
this.detail = { field, actual, bound, reason: resolvedReason };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function shadowBoundExpected(field: string, bound: ShadowInvalidConfigBound): string {
|
|
204
|
+
switch (bound.kind) {
|
|
205
|
+
case 'range':
|
|
206
|
+
return `${field} in [${bound.min}, ${bound.max}]`;
|
|
207
|
+
case 'lower-bound':
|
|
208
|
+
return `${field} ${bound.operator} ${bound.value}`;
|
|
209
|
+
case 'allowed-values':
|
|
210
|
+
return `${field} in {${bound.values.join(', ')}}`;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function shadowBoundReason(bound: ShadowInvalidConfigBound): string {
|
|
215
|
+
switch (bound.kind) {
|
|
216
|
+
case 'range':
|
|
217
|
+
return `a value in [${bound.min}, ${bound.max}]`;
|
|
218
|
+
case 'lower-bound':
|
|
219
|
+
return `a value ${bound.operator} ${bound.value}`;
|
|
220
|
+
case 'allowed-values':
|
|
221
|
+
return `one of [${bound.values.join(', ')}]`;
|
|
220
222
|
}
|
|
221
223
|
}
|
|
222
224
|
|
|
@@ -270,133 +272,125 @@ export class EquirectProjectionFailedError extends Error {
|
|
|
270
272
|
}
|
|
271
273
|
}
|
|
272
274
|
|
|
273
|
-
// ──
|
|
275
|
+
// ── StandardLightBudgetExceededError ──────────────────────────────────────
|
|
274
276
|
|
|
275
|
-
/**
|
|
276
|
-
|
|
277
|
-
*
|
|
278
|
-
* Emitted per-frame (once-per-frame fire) when light count exceeds HDRP budget.
|
|
279
|
-
*/
|
|
280
|
-
export interface HdrpLightBudgetExceededDetail {
|
|
277
|
+
/** The finite local-light budget that a Standard frame agreed to admit. */
|
|
278
|
+
export interface StandardLightBudgetExceededDetail {
|
|
281
279
|
readonly actual: number;
|
|
282
280
|
readonly budget: number;
|
|
283
281
|
}
|
|
284
282
|
|
|
285
283
|
/**
|
|
286
|
-
* Structured
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
* exceeds the HDRP budget (256). Fail-soft: fire once per frame, truncate to 256.
|
|
290
|
-
* - `.code = 'hdrp-light-budget-exceeded'` (closed RuntimeErrorCode)
|
|
291
|
-
* - `.expected` — 'light count <= 256'
|
|
292
|
-
* - `.hint` — 'reduce world light count or increase budget (OOS-hdrp-larger-budget)'
|
|
293
|
-
* - `.detail = { actual, budget }`
|
|
284
|
+
* Structured refusal for a Standard frame whose finite local-light set is
|
|
285
|
+
* outside the selected profile budget. The frame is rejected as a whole; the
|
|
286
|
+
* record owner must not slice the input or submit a partial membership set.
|
|
294
287
|
*/
|
|
295
|
-
export class
|
|
296
|
-
readonly code = '
|
|
288
|
+
export class StandardLightBudgetExceededError extends Error {
|
|
289
|
+
readonly code = 'standard-light-budget-exceeded' as const;
|
|
297
290
|
readonly expected: string;
|
|
298
291
|
readonly hint: string;
|
|
299
|
-
readonly detail:
|
|
292
|
+
readonly detail: StandardLightBudgetExceededDetail;
|
|
300
293
|
|
|
301
294
|
constructor(actual: number, budget: number) {
|
|
302
295
|
const expected = `light count <= ${budget}`;
|
|
303
296
|
const hint =
|
|
304
|
-
`${actual} lights exceed
|
|
305
|
-
'
|
|
306
|
-
super(`
|
|
307
|
-
this.name = '
|
|
297
|
+
`${actual} finite local lights exceed Standard budget ${budget}; ` +
|
|
298
|
+
'reduce the local-light set or select a profile with a supported budget';
|
|
299
|
+
super(`Standard light budget exceeded: ${actual} > ${budget}`);
|
|
300
|
+
this.name = 'StandardLightBudgetExceededError';
|
|
308
301
|
this.expected = expected;
|
|
309
302
|
this.hint = hint;
|
|
310
303
|
this.detail = { actual, budget };
|
|
311
304
|
}
|
|
312
305
|
}
|
|
313
306
|
|
|
314
|
-
// ──
|
|
307
|
+
// ── StandardClusterIndexOverflowError ──────────────────────────────────────
|
|
315
308
|
|
|
316
|
-
/**
|
|
317
|
-
|
|
318
|
-
*
|
|
319
|
-
* Emitted per-frame (once-per-frame fire) when the cluster binner overflows
|
|
320
|
-
* the light index list capacity (65536). Upgraded from ClusterBinError.
|
|
321
|
-
*/
|
|
322
|
-
export interface HdrpIndexListOverflowDetail {
|
|
309
|
+
/** Cluster membership entries that could not fit the single shared index list. */
|
|
310
|
+
export interface StandardClusterIndexOverflowDetail {
|
|
323
311
|
readonly actual: number;
|
|
324
312
|
readonly capacity: number;
|
|
325
313
|
}
|
|
326
314
|
|
|
327
315
|
/**
|
|
328
|
-
* Structured
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
* `ClusterBinError('index-overflow')`. Fail-soft: fire once per frame,
|
|
332
|
-
* continue rendering with what fit.
|
|
333
|
-
* - `.code = 'hdrp-index-list-overflow'` (closed RuntimeErrorCode)
|
|
334
|
-
* - `.expected` — 'light index list entries <= 65536'
|
|
335
|
-
* - `.hint` — 'reduce lights, shrink cluster grid, or increase capacity'
|
|
336
|
-
* - `.detail = { actual, capacity }`
|
|
316
|
+
* Structured refusal for a membership producer that exceeded the shared
|
|
317
|
+
* Cluster index-list capacity. No truncated list is uploaded and no graph is
|
|
318
|
+
* submitted for the rejected frame.
|
|
337
319
|
*/
|
|
338
|
-
export class
|
|
339
|
-
readonly code = '
|
|
320
|
+
export class StandardClusterIndexOverflowError extends Error {
|
|
321
|
+
readonly code = 'standard-cluster-index-overflow' as const;
|
|
340
322
|
readonly expected: string;
|
|
341
323
|
readonly hint: string;
|
|
342
|
-
readonly detail:
|
|
324
|
+
readonly detail: StandardClusterIndexOverflowDetail;
|
|
343
325
|
|
|
344
326
|
constructor(actual: number, capacity: number) {
|
|
345
327
|
const expected = `light index list entries <= ${capacity}`;
|
|
346
328
|
const hint =
|
|
347
329
|
`cluster binner overflow: writeCount ${actual} exceeds capacity ${capacity}; ` +
|
|
348
|
-
'reduce lights
|
|
349
|
-
super(`
|
|
350
|
-
this.name = '
|
|
330
|
+
'reduce finite local lights or choose a supported cluster layout';
|
|
331
|
+
super(`Standard cluster index list overflow: ${actual} > ${capacity}`);
|
|
332
|
+
this.name = 'StandardClusterIndexOverflowError';
|
|
351
333
|
this.expected = expected;
|
|
352
334
|
this.hint = hint;
|
|
353
335
|
this.detail = { actual, capacity };
|
|
354
336
|
}
|
|
355
337
|
}
|
|
356
338
|
|
|
357
|
-
// ──
|
|
339
|
+
// ── StandardClusterTransportUnavailableError ───────────────────────────────
|
|
358
340
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
* Emitted when the Standard clustered lane has fewer than 4 color attachments,
|
|
363
|
-
* meaning the deferred path cannot allocate 3 g-buffer color targets + depth.
|
|
364
|
-
*/
|
|
365
|
-
export interface HdrpDeferredCapsInsufficientDetail {
|
|
366
|
-
readonly actual: number;
|
|
367
|
-
readonly expected: number;
|
|
341
|
+
export interface StandardClusterTransportUnavailableDetail {
|
|
342
|
+
readonly requested: number;
|
|
343
|
+
readonly admitted: 0;
|
|
368
344
|
}
|
|
369
345
|
|
|
370
346
|
/**
|
|
371
|
-
* Structured
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
* - `.code = 'hdrp-deferred-caps-insufficient'` (closed RuntimeErrorCode)
|
|
375
|
-
* - `.expected` — 'maxColorAttachments >= 4'
|
|
376
|
-
* - `.hint` — actionable guidance to upgrade browser or select URP
|
|
377
|
-
* - `.detail = { actual, expected }`
|
|
378
|
-
*
|
|
379
|
-
* @see plan-strategy D-5 (capability validation, no silent fallback)
|
|
347
|
+
* Structured capability refusal. Standard never turns an unproven transport
|
|
348
|
+
* into a smaller direct-light lane; the caller receives the exact requested
|
|
349
|
+
* local-light count and an admitted count of zero.
|
|
380
350
|
*/
|
|
381
|
-
export class
|
|
382
|
-
readonly code = '
|
|
383
|
-
readonly expected
|
|
351
|
+
export class StandardClusterTransportUnavailableError extends Error {
|
|
352
|
+
readonly code = 'standard-cluster-transport-unavailable' as const;
|
|
353
|
+
readonly expected = 'all requested local lights have a proven Cluster transport';
|
|
384
354
|
readonly hint: string;
|
|
385
|
-
readonly detail:
|
|
355
|
+
readonly detail: StandardClusterTransportUnavailableDetail;
|
|
386
356
|
|
|
387
|
-
constructor(
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
super(
|
|
394
|
-
`HDRP deferred caps insufficient: maxColorAttachments = ${actual} (need >= ${_expected})`,
|
|
395
|
-
);
|
|
396
|
-
this.name = 'HdrpDeferredCapsInsufficientError';
|
|
397
|
-
this.expected = _expectedStr;
|
|
357
|
+
constructor(
|
|
358
|
+
requested: number,
|
|
359
|
+
hint = 'enable a proven Cluster storage transport before drawing',
|
|
360
|
+
) {
|
|
361
|
+
super(`Standard Cluster transport unavailable for ${requested} local lights`);
|
|
362
|
+
this.name = 'StandardClusterTransportUnavailableError';
|
|
398
363
|
this.hint = hint;
|
|
399
|
-
this.detail = {
|
|
364
|
+
this.detail = { requested, admitted: 0 };
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// ── StandardProfileInvalidError ───────────────────────────────────────────
|
|
369
|
+
|
|
370
|
+
export interface StandardProfileInvalidDetail {
|
|
371
|
+
readonly field: string;
|
|
372
|
+
readonly actual: unknown;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** Structured validation failure for the single Standard profile surface. */
|
|
376
|
+
export class StandardProfileInvalidError extends Error {
|
|
377
|
+
readonly code = 'standard-profile-invalid' as const;
|
|
378
|
+
readonly expected: string;
|
|
379
|
+
readonly hint: string;
|
|
380
|
+
readonly detail: StandardProfileInvalidDetail;
|
|
381
|
+
|
|
382
|
+
constructor(message: string, detail?: StandardProfileInvalidDetail) {
|
|
383
|
+
super(message);
|
|
384
|
+
this.name = 'StandardProfileInvalidError';
|
|
385
|
+
this.detail = detail ?? { field: 'profile', actual: message };
|
|
386
|
+
if (this.detail.field === 'clusterGrid') {
|
|
387
|
+
this.expected = 'clusterGrid.{x,y,z} each positive integer in [1, 64]';
|
|
388
|
+
this.hint =
|
|
389
|
+
'set clusterGrid.x, clusterGrid.y, and clusterGrid.z to positive integers in [1, 64]';
|
|
390
|
+
} else {
|
|
391
|
+
this.expected = 'StandardProfile contains only supported fields and values';
|
|
392
|
+
this.hint = 'repair the Standard profile fields and retry setProfile';
|
|
393
|
+
}
|
|
400
394
|
}
|
|
401
395
|
}
|
|
402
396
|
|
|
@@ -452,7 +446,7 @@ export interface PointShadowAtlasBoundsViolationDetail {
|
|
|
452
446
|
* - `.code = 'point-shadow-atlas-bounds-violation'`
|
|
453
447
|
* - `.expected` — `0 <= layer < layers && 0 <= face < 6`
|
|
454
448
|
* - `.hint` — clamp `shadowAtlasLayer` or face index before calling
|
|
455
|
-
* `faceView`; the cap
|
|
449
|
+
* `faceView`; the layer cap is the renderer-owned ShadowAtlas capacity
|
|
456
450
|
* - `.detail = { axis, value, max }` — discriminates layer vs face
|
|
457
451
|
*/
|
|
458
452
|
export class PointShadowAtlasBoundsViolationError extends Error {
|
|
@@ -1531,6 +1525,149 @@ export class PointsLinesPrepareFailedError extends Error {
|
|
|
1531
1525
|
}
|
|
1532
1526
|
}
|
|
1533
1527
|
|
|
1528
|
+
// -- RenderTarget errors ------------------------------------------------------
|
|
1529
|
+
|
|
1530
|
+
export interface RenderTargetDescriptorInvalidDetail {
|
|
1531
|
+
readonly field: string;
|
|
1532
|
+
readonly value: unknown;
|
|
1533
|
+
readonly expected: string;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
export class RenderTargetDescriptorInvalidError extends Error {
|
|
1537
|
+
readonly code = 'render-target-descriptor-invalid' as const;
|
|
1538
|
+
readonly expected: string;
|
|
1539
|
+
readonly hint: string;
|
|
1540
|
+
readonly detail: RenderTargetDescriptorInvalidDetail;
|
|
1541
|
+
|
|
1542
|
+
constructor(detail: RenderTargetDescriptorInvalidDetail) {
|
|
1543
|
+
super(`render-target-descriptor-invalid: ${detail.field} does not satisfy ${detail.expected}`);
|
|
1544
|
+
this.name = 'RenderTargetDescriptorInvalidError';
|
|
1545
|
+
this.expected = detail.expected;
|
|
1546
|
+
this.hint = `set RenderTargetDescriptor.${detail.field} to the expected value, then retry create or resize`;
|
|
1547
|
+
this.detail = detail;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
export interface RenderTargetCapabilityMissingDetail {
|
|
1552
|
+
readonly operation: 'create' | 'resize' | 'source' | 'readback';
|
|
1553
|
+
readonly requested: string;
|
|
1554
|
+
readonly capability: string;
|
|
1555
|
+
readonly actual: string;
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
export class RenderTargetCapabilityMissingError extends Error {
|
|
1559
|
+
readonly code = 'render-target-capability-missing' as const;
|
|
1560
|
+
readonly expected: string;
|
|
1561
|
+
readonly hint: string;
|
|
1562
|
+
readonly detail: RenderTargetCapabilityMissingDetail;
|
|
1563
|
+
|
|
1564
|
+
constructor(detail: RenderTargetCapabilityMissingDetail) {
|
|
1565
|
+
super(
|
|
1566
|
+
`render-target-capability-missing: ${detail.capability} does not admit ${detail.requested}`,
|
|
1567
|
+
);
|
|
1568
|
+
this.name = 'RenderTargetCapabilityMissingError';
|
|
1569
|
+
this.expected = `${detail.capability} admits ${detail.requested}`;
|
|
1570
|
+
this.hint = `choose an admitted target descriptor or use a backend providing ${detail.capability}`;
|
|
1571
|
+
this.detail = detail;
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
export type RenderTargetStateInvalidReason =
|
|
1576
|
+
| 'foreign-renderer'
|
|
1577
|
+
| 'destroyed'
|
|
1578
|
+
| 'uninitialized'
|
|
1579
|
+
| 'generation-mismatch'
|
|
1580
|
+
| 'readback-without-intent';
|
|
1581
|
+
|
|
1582
|
+
export interface RenderTargetStateInvalidDetail {
|
|
1583
|
+
readonly operation: 'inspect' | 'resize' | 'source' | 'readback' | 'destroy';
|
|
1584
|
+
readonly reason: RenderTargetStateInvalidReason;
|
|
1585
|
+
readonly state: 'uninitialized' | 'candidate' | 'active' | 'rebuilding' | 'destroyed';
|
|
1586
|
+
readonly generation: number;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
export class RenderTargetStateInvalidError extends Error {
|
|
1590
|
+
readonly code = 'render-target-state-invalid' as const;
|
|
1591
|
+
readonly expected: string;
|
|
1592
|
+
readonly hint: string;
|
|
1593
|
+
readonly detail: RenderTargetStateInvalidDetail;
|
|
1594
|
+
|
|
1595
|
+
constructor(detail: RenderTargetStateInvalidDetail) {
|
|
1596
|
+
super(`render-target-state-invalid: ${detail.operation} cannot use ${detail.reason}`);
|
|
1597
|
+
this.name = 'RenderTargetStateInvalidError';
|
|
1598
|
+
this.expected = `target state permits ${detail.operation}`;
|
|
1599
|
+
this.hint =
|
|
1600
|
+
'use the Renderer that created the target, then initialize, recover, or stop using the destroyed token';
|
|
1601
|
+
this.detail = detail;
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
export interface RenderTargetOperationFailedDetail {
|
|
1606
|
+
readonly operation: 'create' | 'resize' | 'source' | 'readback' | 'destroy' | 'recover';
|
|
1607
|
+
readonly stage: 'allocation' | 'compile' | 'write' | 'submit' | 'copy' | 'retire';
|
|
1608
|
+
readonly generation: number;
|
|
1609
|
+
readonly cause: unknown;
|
|
1610
|
+
readonly recovery: 'retry' | 'recover' | 'retain-last-known-good';
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
export class RenderTargetOperationFailedError extends Error {
|
|
1614
|
+
readonly code = 'render-target-operation-failed' as const;
|
|
1615
|
+
readonly expected: string;
|
|
1616
|
+
readonly hint: string;
|
|
1617
|
+
readonly detail: RenderTargetOperationFailedDetail;
|
|
1618
|
+
|
|
1619
|
+
constructor(detail: RenderTargetOperationFailedDetail) {
|
|
1620
|
+
super(`render-target-operation-failed: ${detail.operation} failed during ${detail.stage}`);
|
|
1621
|
+
this.name = 'RenderTargetOperationFailedError';
|
|
1622
|
+
this.expected = `${detail.operation} completes ${detail.stage}`;
|
|
1623
|
+
this.hint =
|
|
1624
|
+
'inspect detail.cause, then retry, recover the Renderer, or retain the last-known-good generation';
|
|
1625
|
+
this.detail = detail;
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
export interface ReflectionProbeBudgetExceededDetail {
|
|
1630
|
+
readonly actual: number;
|
|
1631
|
+
readonly budget: number;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
export class ReflectionProbeBudgetExceededError extends Error {
|
|
1635
|
+
readonly code = 'reflection-probe-budget-exceeded' as const;
|
|
1636
|
+
readonly expected: string;
|
|
1637
|
+
readonly hint: string;
|
|
1638
|
+
readonly detail: ReflectionProbeBudgetExceededDetail;
|
|
1639
|
+
|
|
1640
|
+
constructor(actual: number, budget: number) {
|
|
1641
|
+
super(`reflection-probe-budget-exceeded: ${actual} > ${budget}`);
|
|
1642
|
+
this.name = 'ReflectionProbeBudgetExceededError';
|
|
1643
|
+
this.expected = `reflection probe work <= ${budget}`;
|
|
1644
|
+
this.hint = 'reduce probe updates for this frame or raise the RenderProfile probe budget';
|
|
1645
|
+
this.detail = { actual, budget };
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
export interface RenderIntentInvalidDetail {
|
|
1650
|
+
readonly component: 'CubeCamera' | 'ReflectionProbe';
|
|
1651
|
+
readonly field: 'updateIntent';
|
|
1652
|
+
readonly value: number;
|
|
1653
|
+
readonly allowed: readonly [0, 1, 2];
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
export class RenderIntentInvalidError extends Error {
|
|
1657
|
+
readonly code = 'render-intent-invalid' as const;
|
|
1658
|
+
readonly expected: string;
|
|
1659
|
+
readonly hint: string;
|
|
1660
|
+
readonly detail: RenderIntentInvalidDetail;
|
|
1661
|
+
|
|
1662
|
+
constructor(component: RenderIntentInvalidDetail['component'], value: number) {
|
|
1663
|
+
super(`render-intent-invalid: ${component}.updateIntent is not an admitted value`);
|
|
1664
|
+
this.name = 'RenderIntentInvalidError';
|
|
1665
|
+
this.expected = `${component}.updateIntent is one of 0, 1, or 2`;
|
|
1666
|
+
this.hint = `set ${component}.updateIntent to 0, 1, or 2`;
|
|
1667
|
+
this.detail = { component, field: 'updateIntent', value, allowed: [0, 1, 2] };
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1534
1671
|
export interface VolumeOwnerConflictDetail {
|
|
1535
1672
|
readonly ownerCount: number;
|
|
1536
1673
|
}
|
|
@@ -1652,9 +1789,10 @@ export type RenderError =
|
|
|
1652
1789
|
| TaaUnavailableError
|
|
1653
1790
|
| ShadowInvalidConfigError
|
|
1654
1791
|
| EquirectProjectionFailedError
|
|
1655
|
-
|
|
|
1656
|
-
|
|
|
1657
|
-
|
|
|
1792
|
+
| StandardLightBudgetExceededError
|
|
1793
|
+
| StandardClusterIndexOverflowError
|
|
1794
|
+
| StandardClusterTransportUnavailableError
|
|
1795
|
+
| StandardProfileInvalidError
|
|
1658
1796
|
| PointShadowAtlasUninitializedError
|
|
1659
1797
|
| PointShadowAtlasBoundsViolationError
|
|
1660
1798
|
| VideoUploadUnsupportedError
|
|
@@ -1683,5 +1821,11 @@ export type RenderError =
|
|
|
1683
1821
|
| PointsLinesMaterialUnsupportedError
|
|
1684
1822
|
| PointsLinesBudgetExceededError
|
|
1685
1823
|
| PointsLinesPrepareFailedError
|
|
1824
|
+
| RenderTargetDescriptorInvalidError
|
|
1825
|
+
| RenderTargetCapabilityMissingError
|
|
1826
|
+
| RenderTargetStateInvalidError
|
|
1827
|
+
| RenderTargetOperationFailedError
|
|
1828
|
+
| ReflectionProbeBudgetExceededError
|
|
1829
|
+
| RenderIntentInvalidError
|
|
1686
1830
|
| ProjectorBindingError
|
|
1687
1831
|
| VolumeError;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// @forgeax/engine-render - Directional CSM projection owner.
|
|
2
|
+
|
|
3
|
+
import type { DirectionalShadowQuality } from '../components/directional-shadow-filter';
|
|
4
|
+
import { directionalShadowQualityFromF32 } from '../components/directional-shadow-filter';
|
|
5
|
+
|
|
6
|
+
/** Light-space bounds produced by one existing orthographic CSM fit. */
|
|
7
|
+
export interface DirectionalShadowCascadeFit {
|
|
8
|
+
readonly split: number;
|
|
9
|
+
readonly minX: number;
|
|
10
|
+
readonly maxX: number;
|
|
11
|
+
readonly minY: number;
|
|
12
|
+
readonly maxY: number;
|
|
13
|
+
readonly minZ: number;
|
|
14
|
+
readonly maxZ: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Host projection sent to the shared View UBO. */
|
|
18
|
+
export interface DirectionalShadowProjection {
|
|
19
|
+
readonly splitPlanes: Float32Array;
|
|
20
|
+
readonly directionalShadowQuality: DirectionalShadowQuality;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Project accepted Directional author facts and the existing CSM fit into the
|
|
25
|
+
* shared split vec4 lanes. `.x` is the split, `.y` is world units per texel,
|
|
26
|
+
* `.z` is the light-space depth span, and `.w` is reserved for the ABI.
|
|
27
|
+
*/
|
|
28
|
+
export function projectDirectionalShadow(
|
|
29
|
+
fits: readonly DirectionalShadowCascadeFit[],
|
|
30
|
+
mapSize: number,
|
|
31
|
+
shadowFilter: number,
|
|
32
|
+
shadowAngularRadius: number,
|
|
33
|
+
maxPenumbraTexels: number,
|
|
34
|
+
): DirectionalShadowProjection | undefined {
|
|
35
|
+
if (!Number.isFinite(mapSize) || mapSize < 1) return undefined;
|
|
36
|
+
const directionalShadowQuality = directionalShadowQualityFromF32(
|
|
37
|
+
shadowFilter,
|
|
38
|
+
shadowAngularRadius,
|
|
39
|
+
maxPenumbraTexels,
|
|
40
|
+
);
|
|
41
|
+
if (directionalShadowQuality === undefined) return undefined;
|
|
42
|
+
|
|
43
|
+
const splitPlanes = new Float32Array(16);
|
|
44
|
+
for (let index = 0; index < fits.length && index < 4; index += 1) {
|
|
45
|
+
const fit = fits[index];
|
|
46
|
+
if (fit === undefined) continue;
|
|
47
|
+
const width = Math.abs(fit.maxX - fit.minX);
|
|
48
|
+
const height = Math.abs(fit.maxY - fit.minY);
|
|
49
|
+
const depth = Math.abs(fit.maxZ - fit.minZ);
|
|
50
|
+
const worldUnitsPerTexel = Math.max(width, height, Number.EPSILON) / mapSize;
|
|
51
|
+
const lightDepthWorldSpan = Math.max(depth, Number.EPSILON);
|
|
52
|
+
if (!Number.isFinite(worldUnitsPerTexel) || !Number.isFinite(lightDepthWorldSpan)) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
const lane = index * 4;
|
|
56
|
+
splitPlanes[lane] = fit.split;
|
|
57
|
+
splitPlanes[lane + 1] = worldUnitsPerTexel;
|
|
58
|
+
splitPlanes[lane + 2] = lightDepthWorldSpan;
|
|
59
|
+
}
|
|
60
|
+
return { splitPlanes, directionalShadowQuality };
|
|
61
|
+
}
|
|
@@ -76,6 +76,20 @@ export type EnvironmentSource =
|
|
|
76
76
|
|
|
77
77
|
export interface FogFrame extends FogCandidate {}
|
|
78
78
|
|
|
79
|
+
export interface FogParameterIssue {
|
|
80
|
+
readonly field: string;
|
|
81
|
+
readonly value: number;
|
|
82
|
+
readonly expected: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Structured failure retained when an invalid Fog update falls back to LKG. */
|
|
86
|
+
export interface FogSelectionFailure {
|
|
87
|
+
readonly code: string;
|
|
88
|
+
readonly expected: string;
|
|
89
|
+
readonly hint: string;
|
|
90
|
+
readonly detail: Readonly<Record<string, unknown>>;
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
export interface EnvironmentFrame {
|
|
80
94
|
readonly source: EnvironmentSource;
|
|
81
95
|
/** Descriptor of the real environment resource adopted for this frame. */
|
|
@@ -103,6 +117,49 @@ function freezeFog(candidate: FogCandidate): FogFrame {
|
|
|
103
117
|
});
|
|
104
118
|
}
|
|
105
119
|
|
|
120
|
+
/** Validate the bounded Fog domain once for every frame-selection producer. */
|
|
121
|
+
export function validateFogParameters(candidate: FogCandidate): FogParameterIssue | undefined {
|
|
122
|
+
if (candidate.color.length !== 3) {
|
|
123
|
+
return {
|
|
124
|
+
field: 'color',
|
|
125
|
+
value: candidate.color.length,
|
|
126
|
+
expected: 'exactly three finite channels in [0, 1]',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
for (let index = 0; index < candidate.color.length; index += 1) {
|
|
130
|
+
const value = candidate.color[index];
|
|
131
|
+
if (value === undefined || !Number.isFinite(value) || value < 0 || value > 1) {
|
|
132
|
+
return {
|
|
133
|
+
field: `color[${index}]`,
|
|
134
|
+
value: value ?? Number.NaN,
|
|
135
|
+
expected: 'a finite number in [0, 1]',
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (!Number.isFinite(candidate.density) || candidate.density < 0) {
|
|
140
|
+
return { field: 'density', value: candidate.density, expected: 'a finite number >= 0' };
|
|
141
|
+
}
|
|
142
|
+
if (!Number.isFinite(candidate.heightFalloff) || candidate.heightFalloff < 0) {
|
|
143
|
+
return {
|
|
144
|
+
field: 'heightFalloff',
|
|
145
|
+
value: candidate.heightFalloff,
|
|
146
|
+
expected: 'a finite number >= 0',
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (
|
|
150
|
+
!Number.isFinite(candidate.maxOpacity) ||
|
|
151
|
+
candidate.maxOpacity < 0 ||
|
|
152
|
+
candidate.maxOpacity > 1
|
|
153
|
+
) {
|
|
154
|
+
return {
|
|
155
|
+
field: 'maxOpacity',
|
|
156
|
+
value: candidate.maxOpacity,
|
|
157
|
+
expected: 'a finite number in [0, 1]',
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
|
|
106
163
|
function freezeAtmosphere(parameters: AtmosphereParameters): AtmosphereParameters {
|
|
107
164
|
return Object.freeze({ ...parameters });
|
|
108
165
|
}
|