@forgeax/engine-render 0.1.33 → 0.1.35
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 +1062 -127
- package/dist/assembly/backend-contract.d.ts +2 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
- package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
- package/dist/assembly/canvas-draw-guard.d.ts +3 -0
- package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
- package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
- package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
- package/dist/assembly/device-feature-admission.d.ts +2 -2
- package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
- package/dist/assembly/factory.d.ts +1 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +6 -5
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
- package/dist/assembly/material-shader-policy.d.ts +16 -2
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/render-feature-post-processes.d.ts +6 -0
- package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
- package/dist/assembly/render-target-host.d.ts +5 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
- package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-inspection.d.ts +11 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -1
- package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
- package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +1 -1
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +2 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +2 -4
- package/dist/authoring.mjs.map +1 -1
- package/dist/barrel-distortion.d.ts +47 -0
- package/dist/barrel-distortion.d.ts.map +1 -0
- package/dist/chunk-3XUBWRY2.mjs +1842 -0
- package/dist/chunk-3XUBWRY2.mjs.map +1 -0
- package/dist/{chunk-OO3DRYK7.mjs → chunk-G6HDNGY7.mjs} +2400 -1767
- package/dist/chunk-G6HDNGY7.mjs.map +1 -0
- package/dist/{chunk-ZDQWGQW7.mjs → chunk-LM5IE7GF.mjs} +4 -4
- package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
- package/dist/{chunk-VOZWDM3L.mjs → chunk-LNIUIKQ7.mjs} +1514 -498
- package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
- package/dist/chunk-MXTWKZO4.mjs +3268 -0
- package/dist/chunk-MXTWKZO4.mjs.map +1 -0
- package/dist/chunk-MZ4C7EHF.mjs +6942 -0
- package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
- package/dist/chunk-RIPAEGI6.mjs +48 -0
- package/dist/chunk-RIPAEGI6.mjs.map +1 -0
- package/dist/{chunk-LEAXOMYJ.mjs → chunk-SGPUJW3F.mjs} +117 -5
- package/dist/chunk-SGPUJW3F.mjs.map +1 -0
- package/dist/{chunk-PA5DRJNI.mjs → chunk-X2KA6WHM.mjs} +29 -4
- package/dist/chunk-X2KA6WHM.mjs.map +1 -0
- package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
- package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
- package/dist/cloud/density.d.ts +55 -0
- package/dist/cloud/density.d.ts.map +1 -0
- package/dist/cloud/extract.d.ts +25 -0
- package/dist/cloud/extract.d.ts.map +1 -0
- package/dist/cloud/feature.d.ts +57 -0
- package/dist/cloud/feature.d.ts.map +1 -0
- package/dist/cloud/frame-context.d.ts +8 -0
- package/dist/cloud/frame-context.d.ts.map +1 -0
- package/dist/cloud/inspection.d.ts +59 -0
- package/dist/cloud/inspection.d.ts.map +1 -0
- package/dist/cloud/optics.d.ts +56 -0
- package/dist/cloud/optics.d.ts.map +1 -0
- package/dist/cloud/parameters.d.ts +73 -0
- package/dist/cloud/parameters.d.ts.map +1 -0
- package/dist/cloud/resources.d.ts +60 -0
- package/dist/cloud/resources.d.ts.map +1 -0
- package/dist/cloud/shadow.d.ts +42 -0
- package/dist/cloud/shadow.d.ts.map +1 -0
- package/dist/cloud/temporal.d.ts +74 -0
- package/dist/cloud/temporal.d.ts.map +1 -0
- package/dist/components/barrel-distortion.d.ts +13 -0
- package/dist/components/barrel-distortion.d.ts.map +1 -0
- package/dist/components/cloud-layer.d.ts +29 -0
- package/dist/components/cloud-layer.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/instances.d.ts +20 -6
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/construct-renderer.d.ts +1 -1
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +8406 -5785
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +19 -19
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/dynamic-geometry.d.ts +5 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/errors/cloud.d.ts +59 -0
- package/dist/errors/cloud.d.ts.map +1 -0
- package/dist/errors/render.d.ts +20 -5
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/examples/single-layer-medium-surface.d.ts +47 -0
- package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +5 -1
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/material-context.d.ts +7 -0
- package/dist/extract/material-context.d.ts.map +1 -0
- package/dist/features/barrel-distortion.d.ts +29 -0
- package/dist/features/barrel-distortion.d.ts.map +1 -0
- package/dist/features/error-reporting.d.ts +6 -2
- package/dist/features/error-reporting.d.ts.map +1 -1
- package/dist/features/host.d.ts +15 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/plan.d.ts +10 -0
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +5 -0
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +1 -0
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/targets.d.ts +2 -0
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +48 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +15 -7
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/glyph-text-layout-system.d.ts +1 -1
- package/dist/glyph-text-layout-system.d.ts.map +1 -1
- package/dist/gpu-dirty-ranges.d.ts +11 -0
- package/dist/gpu-dirty-ranges.d.ts.map +1 -0
- package/dist/gpu-driven/batch-topology.d.ts +17 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts +6 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster-material.d.ts +178 -0
- package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +47 -3
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/resource-allocation.d.ts +31 -0
- package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
- package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
- package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +26 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +5 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +2 -2
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/frame-resources.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +14 -5
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +30 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +780 -9
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +135 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instance-buffer-cache.d.ts +4 -4
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +47 -100
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +7 -8
- package/dist/internal.mjs.map +1 -1
- package/dist/pbr-pipeline.d.ts +22 -4
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
- package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
- package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
- package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
- package/dist/pipeline/standard-output/resources.d.ts +2 -2
- package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
- package/dist/pipeline/standard-output/types.d.ts +4 -2
- package/dist/pipeline/standard-output/types.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/publication/contract.d.ts +77 -0
- package/dist/publication/contract.d.ts.map +1 -0
- package/dist/publication/dependencies.d.ts +7 -0
- package/dist/publication/dependencies.d.ts.map +1 -0
- package/dist/publication/prepare-geometry.d.ts +9 -0
- package/dist/publication/prepare-geometry.d.ts.map +1 -0
- package/dist/publication/programs.d.ts +5 -0
- package/dist/publication/programs.d.ts.map +1 -0
- package/dist/publication/publisher.d.ts +33 -0
- package/dist/publication/publisher.d.ts.map +1 -0
- package/dist/publication/receiver.d.ts +29 -0
- package/dist/publication/receiver.d.ts.map +1 -0
- package/dist/publication/resource-scope.d.ts +18 -0
- package/dist/publication/resource-scope.d.ts.map +1 -0
- package/dist/publication/targets.d.ts +33 -0
- package/dist/publication/targets.d.ts.map +1 -0
- package/dist/publication/video.d.ts +5 -0
- package/dist/publication/video.d.ts.map +1 -0
- package/dist/record/barrel-distortion-frame.d.ts +15 -0
- package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
- package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
- package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
- package/dist/record/fold-buckets.d.ts +95 -0
- package/dist/record/fold-buckets.d.ts.map +1 -0
- package/dist/record/fold-instance-buffer.d.ts +6 -0
- package/dist/record/fold-instance-buffer.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +1 -0
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +43 -9
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +15 -65
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-draw-receipts.d.ts +11 -0
- package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +8 -0
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +2 -2
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +22 -6
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +14 -10
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +3 -16
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +13 -2
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/motion-blur-receipt.d.ts +11 -0
- package/dist/record/motion-blur-receipt.d.ts.map +1 -0
- package/dist/record/prepared-material-bindings.d.ts +3 -3
- package/dist/record/prepared-material-bindings.d.ts.map +1 -1
- package/dist/record/probe-blend-buffer.d.ts +16 -0
- package/dist/record/probe-blend-buffer.d.ts.map +1 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +24 -5
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -0
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/sprite-instance-buffer.d.ts +31 -0
- package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
- package/dist/record/target-capture-graph.d.ts +19 -0
- package/dist/record/target-capture-graph.d.ts.map +1 -0
- package/dist/record/typed-frame-graph.d.ts +24 -15
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +11 -3
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/record/volume-params.d.ts +9 -0
- package/dist/record/volume-params.d.ts.map +1 -0
- package/dist/recovery/render-system-candidate.d.ts +14 -4
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +46 -5
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +103 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +3 -2
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +18 -9
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-presentation.d.ts +23 -0
- package/dist/render-system-presentation.d.ts.map +1 -0
- package/dist/render-system-producer-roots.d.ts +10 -0
- package/dist/render-system-producer-roots.d.ts.map +1 -0
- package/dist/render-system-projections.d.ts +3 -2
- package/dist/render-system-projections.d.ts.map +1 -1
- package/dist/render-system-residency.d.ts +12 -0
- package/dist/render-system-residency.d.ts.map +1 -0
- package/dist/render-system.d.ts +22 -21
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/probe-blend.d.ts +27 -0
- package/dist/scene/probe-blend.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +18 -7
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/render-source.d.ts +42 -0
- package/dist/scene/render-source.d.ts.map +1 -0
- package/dist/scene/source-systems.d.ts +6 -0
- package/dist/scene/source-systems.d.ts.map +1 -0
- package/dist/ssao-buffers.d.ts +9 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/surface/dynamic-input.d.ts +133 -0
- package/dist/surface/dynamic-input.d.ts.map +1 -0
- package/dist/surface/gpu-driven.d.ts +41 -0
- package/dist/surface/gpu-driven.d.ts.map +1 -0
- package/dist/surface/submission-observation.d.ts +136 -0
- package/dist/surface/submission-observation.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/systems/skin-palette-types.d.ts +10 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -1
- package/dist/systems/transparent-dispatch.d.ts +2 -2
- package/dist/systems/transparent-dispatch.d.ts.map +1 -1
- package/dist/systems/transparent-sort-config.d.ts +2 -1
- package/dist/systems/transparent-sort-config.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts +13 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -7
- package/dist/temporal/inspection.d.ts.map +1 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
- package/dist/transmission/single-layer-medium.d.ts +89 -0
- package/dist/transmission/single-layer-medium.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +14 -2
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +9 -4
- package/dist/volume/component.d.ts.map +1 -1
- package/dist/volume/extract.d.ts +1 -1
- package/dist/volume/extract.d.ts.map +1 -1
- package/dist/volume/inspection.d.ts +2 -0
- package/dist/volume/inspection.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +4 -1
- package/dist/volume/passes.d.ts.map +1 -1
- package/dist/volume/resources.d.ts.map +1 -1
- package/package.json +22 -21
- package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
- package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
- package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
- package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
- package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
- package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
- package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
- package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
- package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
- package/src/__tests__/factory-contract.integration.test.ts +295 -45
- package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
- package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
- package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +5 -6
- package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
- package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
- package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
- package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
- package/src/__tests__/gpu-scene.unit.test.ts +119 -9
- package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
- package/src/__tests__/instances-culling.integration.test.ts +10 -36
- package/src/__tests__/instances-store.unit.test.ts +97 -305
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
- package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +145 -0
- package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
- package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
- package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
- package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
- package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
- package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +66 -8
- package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
- package/src/__tests__/probe-bindings.unit.test.ts +582 -1
- package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
- package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +8 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
- package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
- package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
- package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
- package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
- package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
- package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
- package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -8
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
- package/src/__tests__/resource-allocation.unit.test.ts +123 -0
- package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
- package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
- package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
- package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
- package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
- package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
- package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
- package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
- package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
- package/src/__tests__/temporal-performance.integration.test.ts +3 -3
- package/src/__tests__/visibility-instances.integration.test.ts +7 -19
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
- package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
- package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
- package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
- package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
- package/src/assembly/backend-contract.ts +30 -0
- package/src/assembly/barrel-distortion-inspection.ts +22 -0
- package/src/assembly/canvas-draw-guard.ts +11 -0
- package/src/assembly/cloud-shadow-entry.ts +22 -0
- package/src/assembly/device-feature-admission.ts +2 -2
- package/src/assembly/dynamic-geometry-host.ts +65 -37
- package/src/assembly/dynamic-geometry-runtime.ts +7 -1
- package/src/assembly/factory.ts +2 -30
- package/src/assembly/host-contract.ts +8 -5
- package/src/assembly/material/assembly.ts +25 -13
- package/src/assembly/material/pipeline-helpers.ts +53 -12
- package/src/assembly/material-shader-policy.ts +55 -0
- package/src/assembly/material-shader-prewarm.ts +21 -10
- package/src/assembly/recovery/device-loss-fanout.ts +13 -0
- package/src/assembly/recovery/renderer-recover.ts +50 -18
- package/src/assembly/render-feature-post-processes.ts +54 -0
- package/src/assembly/render-target-host.ts +57 -47
- package/src/assembly/renderer-facade.ts +7 -2
- package/src/assembly/renderer-feature-inspection.ts +8 -2
- package/src/assembly/renderer-frame-transaction.ts +23 -0
- package/src/assembly/renderer-inspection.ts +28 -0
- package/src/assembly/skin-palette-owner.ts +1 -1
- package/src/assembly/temporal-post-process-prewarm.ts +3 -3
- package/src/assembly/webgpu-pbr-ready.ts +9 -1
- package/src/assembly/webgpu-ready-per-pass.ts +104 -0
- package/src/assembly/webgpu-ready.ts +116 -62
- package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
- package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
- package/src/assembly/webgpu-renderer.ts +303 -313
- package/src/assembly/webgpu-vertex-layouts.ts +1 -1
- package/src/barrel-distortion.ts +247 -0
- package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
- package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
- package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
- package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
- package/src/cloud/density.ts +600 -0
- package/src/cloud/extract.ts +110 -0
- package/src/cloud/feature.ts +1810 -0
- package/src/cloud/frame-context.ts +42 -0
- package/src/cloud/inspection.ts +130 -0
- package/src/cloud/optics.ts +285 -0
- package/src/cloud/parameters.ts +255 -0
- package/src/cloud/resources.ts +122 -0
- package/src/cloud/shadow.ts +167 -0
- package/src/cloud/temporal.ts +226 -0
- package/src/components/barrel-distortion.ts +46 -0
- package/src/components/cloud-layer.ts +47 -0
- package/src/components/index.ts +2 -0
- package/src/components/instances.ts +18 -45
- package/src/components/sprite-instances.ts +1 -1
- package/src/construct-renderer.ts +1 -1
- package/src/device/gpu-residency.ts +26 -25
- package/src/dynamic-geometry.ts +12 -1
- package/src/errors/cloud.ts +103 -0
- package/src/errors/render.ts +47 -8
- package/src/examples/single-layer-medium-surface.ts +59 -0
- package/src/extract/camera.ts +15 -1
- package/src/extract/contracts.ts +5 -0
- package/src/extract/material-context.ts +21 -0
- package/src/features/barrel-distortion.ts +172 -0
- package/src/features/error-reporting.ts +26 -6
- package/src/features/host.ts +128 -19
- package/src/features/plan.ts +10 -0
- package/src/features/render-graph-contribution.ts +9 -0
- package/src/features/render-graph-raster.ts +45 -3
- package/src/features/targets.ts +66 -0
- package/src/features/types.ts +51 -0
- package/src/fullscreen-post-process-pass.ts +41 -9
- package/src/glyph-text-layout-system.ts +2 -2
- package/src/gpu-dirty-ranges.ts +48 -0
- package/src/gpu-driven/batch-topology.ts +53 -0
- package/src/gpu-driven/material-artifacts.ts +33 -25
- package/src/gpu-driven/prepared-draw.ts +12 -4
- package/src/gpu-driven/production-raster-material.ts +1894 -0
- package/src/gpu-driven/production-raster.ts +825 -784
- package/src/gpu-driven/resource-allocation.ts +142 -0
- package/src/gpu-driven/shadow-ownership.ts +71 -0
- package/src/gpu-driven/view-gpu.ts +164 -10
- package/src/gpu-scene.ts +75 -84
- package/src/hdrp-buffers.ts +4 -3
- package/src/ibl/frame-resources.ts +0 -1
- package/src/ibl/skylight-bind-group.ts +62 -32
- package/src/index.ts +205 -9
- package/src/inspection-types.ts +162 -0
- package/src/instance-buffer-cache.ts +4 -4
- package/src/instances.ts +152 -569
- package/src/pbr-pipeline.ts +230 -30
- package/src/pipeline/single-layer-medium-passes.ts +267 -0
- package/src/pipeline/standard-forward-lane.ts +313 -57
- package/src/pipeline/standard-output/graph.ts +8 -2
- package/src/pipeline/standard-output/lut-gpu.ts +3 -3
- package/src/pipeline/standard-output/resources.ts +2 -2
- package/src/pipeline/standard-output/types.ts +12 -1
- package/src/pipeline/standard-pipeline.ts +291 -18
- package/src/pipeline/standard-post.ts +90 -24
- package/src/pipeline-builder.ts +1 -1
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
- package/src/prepare/prepared-graphics-resolver.ts +2 -0
- package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
- package/src/publication/__tests__/features.integration.test.ts +122 -0
- package/src/publication/__tests__/programs.unit.test.ts +25 -0
- package/src/publication/__tests__/publication.integration.test.ts +370 -0
- package/src/publication/__tests__/targets.integration.test.ts +120 -0
- package/src/publication/__tests__/video.browser.test.ts +50 -0
- package/src/publication/contract.ts +104 -0
- package/src/publication/dependencies.ts +54 -0
- package/src/publication/prepare-geometry.ts +94 -0
- package/src/publication/programs.ts +45 -0
- package/src/publication/publisher.ts +618 -0
- package/src/publication/receiver.ts +297 -0
- package/src/publication/resource-scope.ts +31 -0
- package/src/publication/targets.ts +182 -0
- package/src/publication/video.ts +33 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +9 -11
- package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
- package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
- package/src/record/barrel-distortion-frame.ts +110 -0
- package/src/record/dynamic-geometry-consumption.ts +39 -9
- package/src/record/fold-buckets.ts +855 -0
- package/src/record/fold-instance-buffer.ts +51 -0
- package/src/record/frame-lighting.ts +36 -2
- package/src/record/frame-snapshot.ts +45 -9
- package/src/record/frame.ts +258 -1105
- package/src/record/gpu-draw-receipts.ts +38 -0
- package/src/record/gpu-timing.ts +48 -5
- package/src/record/helpers.ts +2 -2
- package/src/record/main-pass-geometry.ts +272 -84
- package/src/record/main-pass-material.ts +102 -36
- package/src/record/main-pass-sprite-draws.ts +13 -217
- package/src/record/main-pass.ts +164 -27
- package/src/record/motion-blur-receipt.ts +91 -0
- package/src/record/prepared-material-bindings.ts +11 -6
- package/src/record/probe-blend-buffer.ts +180 -0
- package/src/record/recovery-pipeline.ts +35 -3
- package/src/record/render-context.ts +41 -5
- package/src/record/shadow-pass.ts +30 -4
- package/src/record/skybox-post-pass.ts +28 -4
- package/src/record/sprite-instance-buffer.ts +155 -0
- package/src/record/target-capture-graph.ts +258 -0
- package/src/record/typed-frame-graph.ts +776 -340
- package/src/record/view-ubo.ts +27 -4
- package/src/record/volume-params.ts +225 -0
- package/src/recovery/render-system-candidate.ts +243 -50
- package/src/reflection/record-owner.ts +7 -3
- package/src/render-contract.ts +54 -5
- package/src/render-graph-primitives.ts +7 -1
- package/src/render-pipeline.ts +130 -0
- package/src/render-system-extract-tail.ts +90 -78
- package/src/render-system-extract.ts +76 -76
- package/src/render-system-presentation.ts +56 -0
- package/src/render-system-producer-roots.ts +96 -0
- package/src/render-system-projections.ts +3 -2
- package/src/render-system-residency.ts +159 -0
- package/src/render-system.ts +421 -408
- package/src/scene/probe-blend.ts +96 -4
- package/src/scene/render-scene.ts +416 -337
- package/src/scene/render-source.ts +90 -0
- package/src/scene/source-systems.ts +33 -0
- package/src/ssao-buffers.ts +95 -2
- package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
- package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
- package/src/surface/dynamic-input.ts +658 -0
- package/src/surface/gpu-driven.ts +147 -0
- package/src/surface/submission-observation.ts +517 -0
- package/src/systems/skin-palette-allocator.ts +5 -1
- package/src/systems/skin-palette-types.ts +11 -0
- package/src/systems/transparent-dispatch.ts +2 -2
- package/src/systems/transparent-sort-config.ts +3 -1
- package/src/temporal/gpu.ts +101 -17
- package/src/temporal/inspection.ts +7 -1
- package/src/temporal/standard-scene-data.ts +5 -0
- package/src/temporal/target-coverage-attachment.ts +4 -0
- package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
- package/src/transmission/single-layer-medium.ts +322 -0
- package/src/typed-render-graph-primitives.ts +70 -2
- package/src/volume/component.ts +10 -9
- package/src/volume/extract.ts +11 -5
- package/src/volume/inspection.ts +3 -0
- package/src/volume/passes.ts +87 -4
- package/src/volume/resources.ts +2 -1
- package/dist/chunk-3RTCJTH4.mjs +0 -1610
- package/dist/chunk-3RTCJTH4.mjs.map +0 -1
- package/dist/chunk-BLXGONR2.mjs.map +0 -1
- package/dist/chunk-ILQ5MEZF.mjs +0 -32
- package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
- package/dist/chunk-LEAXOMYJ.mjs.map +0 -1
- package/dist/chunk-NB2S7ZRX.mjs +0 -1783
- package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
- package/dist/chunk-NNQL7CB3.mjs +0 -1713
- package/dist/chunk-NNQL7CB3.mjs.map +0 -1
- package/dist/chunk-OO3DRYK7.mjs.map +0 -1
- package/dist/chunk-PA5DRJNI.mjs.map +0 -1
- package/dist/chunk-PLAXOOX5.mjs +0 -1907
- package/dist/chunk-PLAXOOX5.mjs.map +0 -1
- package/dist/chunk-RXZ3RGOU.mjs +0 -53
- package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
- package/dist/chunk-VOZWDM3L.mjs.map +0 -1
|
@@ -0,0 +1,3268 @@
|
|
|
1
|
+
import { err, ok, derive } from '@forgeax/engine-types';
|
|
2
|
+
import { cubeArrayDepthDescriptor, comparisonSamplerDescriptor, cubeArrayDepthFaceView } from '@forgeax/engine-rhi';
|
|
3
|
+
import { vec3 } from '@forgeax/engine-math';
|
|
4
|
+
import { InstanceTransformsStrideMismatchError } from '@forgeax/engine-ecs/projection';
|
|
5
|
+
import { STANDARD_PIPELINE_PARAM_SCHEMA, standardPhysicalTextureFields, STANDARD_PHYSICAL_TEXTURE_FIELDS } from '@forgeax/engine-shader';
|
|
6
|
+
import { deriveVertexLayoutProjection } from '@forgeax/engine-geometry';
|
|
7
|
+
|
|
8
|
+
// src/pipeline/standard-output/auto-exposure/inspection.ts
|
|
9
|
+
var AutoExposureInvalidParameterError = class extends Error {
|
|
10
|
+
constructor(detail) {
|
|
11
|
+
super(`auto-exposure-invalid-parameter: ${detail.field}`);
|
|
12
|
+
this.detail = detail;
|
|
13
|
+
this.name = "AutoExposureInvalidParameterError";
|
|
14
|
+
}
|
|
15
|
+
detail;
|
|
16
|
+
code = "auto-exposure-invalid-parameter";
|
|
17
|
+
expected = ERROR_POLICY[this.code].expected;
|
|
18
|
+
hint = ERROR_POLICY[this.code].hint;
|
|
19
|
+
};
|
|
20
|
+
var AutoExposureCapabilityUnavailableError = class extends Error {
|
|
21
|
+
constructor(detail) {
|
|
22
|
+
super(`auto-exposure-capability-unavailable: ${detail.capability}`);
|
|
23
|
+
this.detail = detail;
|
|
24
|
+
this.name = "AutoExposureCapabilityUnavailableError";
|
|
25
|
+
}
|
|
26
|
+
detail;
|
|
27
|
+
code = "auto-exposure-capability-unavailable";
|
|
28
|
+
expected = ERROR_POLICY[this.code].expected;
|
|
29
|
+
hint = ERROR_POLICY[this.code].hint;
|
|
30
|
+
};
|
|
31
|
+
var AutoExposureStaleGenerationError = class extends Error {
|
|
32
|
+
constructor(detail) {
|
|
33
|
+
super(
|
|
34
|
+
`auto-exposure-stale-generation: ${detail.actualGeneration} != ${detail.expectedGeneration}`
|
|
35
|
+
);
|
|
36
|
+
this.detail = detail;
|
|
37
|
+
this.name = "AutoExposureStaleGenerationError";
|
|
38
|
+
}
|
|
39
|
+
detail;
|
|
40
|
+
code = "auto-exposure-stale-generation";
|
|
41
|
+
expected = ERROR_POLICY[this.code].expected;
|
|
42
|
+
hint = ERROR_POLICY[this.code].hint;
|
|
43
|
+
};
|
|
44
|
+
var AutoExposureStageFailedError = class extends Error {
|
|
45
|
+
constructor(detail) {
|
|
46
|
+
super(`auto-exposure-stage-failed: ${detail.operation}`);
|
|
47
|
+
this.detail = detail;
|
|
48
|
+
this.name = "AutoExposureStageFailedError";
|
|
49
|
+
}
|
|
50
|
+
detail;
|
|
51
|
+
code = "auto-exposure-stage-failed";
|
|
52
|
+
expected = ERROR_POLICY[this.code].expected;
|
|
53
|
+
hint = ERROR_POLICY[this.code].hint;
|
|
54
|
+
};
|
|
55
|
+
var ERROR_POLICY = {
|
|
56
|
+
"auto-exposure-invalid-parameter": {
|
|
57
|
+
expected: "camera auto-exposure parameters are finite and within their declared ranges",
|
|
58
|
+
hint: "inspect the field and provide a finite value before rebuilding the camera output"
|
|
59
|
+
},
|
|
60
|
+
"auto-exposure-capability-unavailable": {
|
|
61
|
+
expected: "the auto-exposure stage has the required device capability",
|
|
62
|
+
hint: "inspect live capabilities and retry the same camera generation"
|
|
63
|
+
},
|
|
64
|
+
"auto-exposure-stale-generation": {
|
|
65
|
+
expected: "the prepared auto-exposure state matches the camera target generation",
|
|
66
|
+
hint: "discard stale prepared state and rebuild from the latest camera snapshot"
|
|
67
|
+
},
|
|
68
|
+
"auto-exposure-stage-failed": {
|
|
69
|
+
expected: "the auto-exposure stage completes its declared operation",
|
|
70
|
+
hint: "inspect the structured cause, preserve lastKnownGood, and retry the stage"
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
function createAutoExposureError(input) {
|
|
74
|
+
if (input instanceof AutoExposureInvalidParameterError || input instanceof AutoExposureCapabilityUnavailableError || input instanceof AutoExposureStaleGenerationError || input instanceof AutoExposureStageFailedError) {
|
|
75
|
+
return input;
|
|
76
|
+
}
|
|
77
|
+
switch (input.code) {
|
|
78
|
+
case "auto-exposure-invalid-parameter":
|
|
79
|
+
return new AutoExposureInvalidParameterError(input.detail);
|
|
80
|
+
case "auto-exposure-capability-unavailable":
|
|
81
|
+
return new AutoExposureCapabilityUnavailableError(input.detail);
|
|
82
|
+
case "auto-exposure-stale-generation":
|
|
83
|
+
return new AutoExposureStaleGenerationError(input.detail);
|
|
84
|
+
case "auto-exposure-stage-failed":
|
|
85
|
+
return new AutoExposureStageFailedError(input.detail);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function cloneExposure(exposure) {
|
|
89
|
+
if (exposure.kind === "manual") return { ...exposure };
|
|
90
|
+
return {
|
|
91
|
+
...exposure,
|
|
92
|
+
rangeEv: [exposure.rangeEv[0], exposure.rangeEv[1]],
|
|
93
|
+
rates: [exposure.rates[0], exposure.rates[1]]
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function cloneFailure(error) {
|
|
97
|
+
if (error === void 0) return void 0;
|
|
98
|
+
return Object.freeze({
|
|
99
|
+
...error,
|
|
100
|
+
detail: Object.freeze({ ...error.detail })
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function createAutoExposureInspection(input) {
|
|
104
|
+
const base = {
|
|
105
|
+
requested: cloneExposure(input.requested),
|
|
106
|
+
actual: input.actual,
|
|
107
|
+
actualState: input.actualState ?? (input.actual === null ? "gpu-resident" : "accepted"),
|
|
108
|
+
fallback: input.fallback,
|
|
109
|
+
lastKnownGood: input.lastKnownGood,
|
|
110
|
+
targetGeneration: input.targetGeneration,
|
|
111
|
+
reset: Object.freeze([...input.reset]),
|
|
112
|
+
cost: Object.freeze({ ...input.cost }),
|
|
113
|
+
receipt: Object.freeze({ ...input.receipt })
|
|
114
|
+
};
|
|
115
|
+
if (input.recentFailure === void 0) return Object.freeze(base);
|
|
116
|
+
const recentFailure = cloneFailure(createAutoExposureError(input.recentFailure));
|
|
117
|
+
if (recentFailure === void 0) return Object.freeze(base);
|
|
118
|
+
return Object.freeze({ ...base, recentFailure });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/errors/render.ts
|
|
122
|
+
var LifecycleConstructionError = class extends Error {
|
|
123
|
+
code = "lifecycle-construction-failed";
|
|
124
|
+
expected = "all DeviceScope resources establish and terminate in order";
|
|
125
|
+
hint = "inspect detail and cleanupFailures, then recover or rebuild the DeviceScope";
|
|
126
|
+
detail;
|
|
127
|
+
constructor(detail) {
|
|
128
|
+
super(`lifecycle-construction-failed: ${detail.resourceKind} lifecycle transaction failed`);
|
|
129
|
+
this.name = "LifecycleConstructionError";
|
|
130
|
+
this.detail = detail;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var LightResourceUnavailableError = class extends Error {
|
|
134
|
+
code = "light-resource-unavailable";
|
|
135
|
+
expected;
|
|
136
|
+
hint;
|
|
137
|
+
detail;
|
|
138
|
+
constructor(detail, expected, actual, hint) {
|
|
139
|
+
super(`light-resource-unavailable: ${detail.feature} ${actual}`);
|
|
140
|
+
this.name = "LightResourceUnavailableError";
|
|
141
|
+
this.expected = expected;
|
|
142
|
+
this.hint = hint;
|
|
143
|
+
this.detail = detail;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
function createLightResourceUnavailable(input) {
|
|
147
|
+
return new LightResourceUnavailableError(
|
|
148
|
+
{
|
|
149
|
+
entity: input.entity,
|
|
150
|
+
feature: input.feature,
|
|
151
|
+
generation: input.generation,
|
|
152
|
+
sourceKey: input.sourceKey,
|
|
153
|
+
reason: input.reason
|
|
154
|
+
},
|
|
155
|
+
input.expected,
|
|
156
|
+
input.actual,
|
|
157
|
+
input.hint
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
var TemporalFrameSubmitError = class extends Error {
|
|
161
|
+
code = "temporal-frame-submit-rejected";
|
|
162
|
+
expected = "the staged frame is accepted by queue.submit before temporal facts advance";
|
|
163
|
+
hint = "inspect the queue submission and retry the frame after the device is available";
|
|
164
|
+
detail;
|
|
165
|
+
constructor(reason) {
|
|
166
|
+
super(`temporal-frame-submit-rejected: ${reason}`);
|
|
167
|
+
this.name = "TemporalFrameSubmitError";
|
|
168
|
+
this.detail = { reason };
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
var ShadowInvalidConfigError = class extends Error {
|
|
172
|
+
code = "shadow-invalid-config";
|
|
173
|
+
expected;
|
|
174
|
+
hint;
|
|
175
|
+
detail;
|
|
176
|
+
constructor(field, actual, minOrBound, maxOrComparator, reason) {
|
|
177
|
+
const bound = typeof minOrBound === "number" ? typeof maxOrComparator === "number" ? { kind: "range", min: minOrBound, max: maxOrComparator } : {
|
|
178
|
+
kind: "lower-bound",
|
|
179
|
+
operator: maxOrComparator === ">" ? ">" : ">=",
|
|
180
|
+
value: minOrBound
|
|
181
|
+
} : minOrBound;
|
|
182
|
+
const resolvedReason = reason ?? shadowBoundReason(bound);
|
|
183
|
+
const expected = shadowBoundExpected(field, bound);
|
|
184
|
+
const hint = `set ${field} to ${resolvedReason}; got ${actual}`;
|
|
185
|
+
super(`shadow component .${field} is invalid: ${resolvedReason}; got ${actual}`);
|
|
186
|
+
this.name = "ShadowInvalidConfigError";
|
|
187
|
+
this.hint = hint;
|
|
188
|
+
this.expected = expected;
|
|
189
|
+
this.detail = { field, actual, bound, reason: resolvedReason };
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
function shadowBoundExpected(field, bound) {
|
|
193
|
+
switch (bound.kind) {
|
|
194
|
+
case "range":
|
|
195
|
+
return `${field} in [${bound.min}, ${bound.max}]`;
|
|
196
|
+
case "lower-bound":
|
|
197
|
+
return `${field} ${bound.operator} ${bound.value}`;
|
|
198
|
+
case "allowed-values":
|
|
199
|
+
return `${field} in {${bound.values.join(", ")}}`;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function shadowBoundReason(bound) {
|
|
203
|
+
switch (bound.kind) {
|
|
204
|
+
case "range":
|
|
205
|
+
return `a value in [${bound.min}, ${bound.max}]`;
|
|
206
|
+
case "lower-bound":
|
|
207
|
+
return `a value ${bound.operator} ${bound.value}`;
|
|
208
|
+
case "allowed-values":
|
|
209
|
+
return `one of [${bound.values.join(", ")}]`;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
var EquirectProjectionFailedError = class extends Error {
|
|
213
|
+
code = "equirect-projection-failed";
|
|
214
|
+
expected;
|
|
215
|
+
hint;
|
|
216
|
+
detail;
|
|
217
|
+
constructor(handle) {
|
|
218
|
+
const expected = `equirect handle ${handle} projects to a GPU cubemap + IBL precompute`;
|
|
219
|
+
const hint = `equirect handle ${handle} referenced by Skylight/SkyboxBackground failed projection; declare Skylight{equirect} with a valid HDR equirect source and check device.caps.rgba16floatRenderable. The projection is internal (no user upload call); the record arm does not retry`;
|
|
220
|
+
super(`equirect handle ${handle} cubemap projection failed`);
|
|
221
|
+
this.name = "EquirectProjectionFailedError";
|
|
222
|
+
this.expected = expected;
|
|
223
|
+
this.hint = hint;
|
|
224
|
+
this.detail = { handle };
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
var StandardLightBudgetExceededError = class extends Error {
|
|
228
|
+
code = "standard-light-budget-exceeded";
|
|
229
|
+
expected;
|
|
230
|
+
hint;
|
|
231
|
+
detail;
|
|
232
|
+
constructor(actual, budget) {
|
|
233
|
+
const expected = `light count <= ${budget}`;
|
|
234
|
+
const hint = `${actual} finite local lights exceed Standard budget ${budget}; reduce the local-light set or select a profile with a supported budget`;
|
|
235
|
+
super(`Standard light budget exceeded: ${actual} > ${budget}`);
|
|
236
|
+
this.name = "StandardLightBudgetExceededError";
|
|
237
|
+
this.expected = expected;
|
|
238
|
+
this.hint = hint;
|
|
239
|
+
this.detail = { actual, budget };
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
var StandardClusterIndexOverflowError = class extends Error {
|
|
243
|
+
code = "standard-cluster-index-overflow";
|
|
244
|
+
expected;
|
|
245
|
+
hint;
|
|
246
|
+
detail;
|
|
247
|
+
constructor(actual, capacity) {
|
|
248
|
+
const expected = `light index list entries <= ${capacity}`;
|
|
249
|
+
const hint = `cluster binner overflow: writeCount ${actual} exceeds capacity ${capacity}; reduce finite local lights or choose a supported cluster layout`;
|
|
250
|
+
super(`Standard cluster index list overflow: ${actual} > ${capacity}`);
|
|
251
|
+
this.name = "StandardClusterIndexOverflowError";
|
|
252
|
+
this.expected = expected;
|
|
253
|
+
this.hint = hint;
|
|
254
|
+
this.detail = { actual, capacity };
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
var StandardClusterTransportUnavailableError = class extends Error {
|
|
258
|
+
code = "standard-cluster-transport-unavailable";
|
|
259
|
+
expected = "all requested local lights have a proven Cluster transport";
|
|
260
|
+
hint;
|
|
261
|
+
detail;
|
|
262
|
+
constructor(requested, hint = "enable a proven Cluster storage transport before drawing") {
|
|
263
|
+
super(`Standard Cluster transport unavailable for ${requested} local lights`);
|
|
264
|
+
this.name = "StandardClusterTransportUnavailableError";
|
|
265
|
+
this.hint = hint;
|
|
266
|
+
this.detail = { requested, admitted: 0 };
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
var StandardProfileInvalidError = class extends Error {
|
|
270
|
+
code = "standard-profile-invalid";
|
|
271
|
+
expected;
|
|
272
|
+
hint;
|
|
273
|
+
detail;
|
|
274
|
+
constructor(message, detail) {
|
|
275
|
+
super(message);
|
|
276
|
+
this.name = "StandardProfileInvalidError";
|
|
277
|
+
this.detail = detail ?? { field: "profile", actual: message };
|
|
278
|
+
if (this.detail.field === "clusterGrid") {
|
|
279
|
+
this.expected = "clusterGrid.{x,y,z} each positive integer in [1, 64]";
|
|
280
|
+
this.hint = "set clusterGrid.x, clusterGrid.y, and clusterGrid.z to positive integers in [1, 64]";
|
|
281
|
+
} else {
|
|
282
|
+
this.expected = "StandardProfile contains only supported fields and values";
|
|
283
|
+
this.hint = "repair the Standard profile fields and retry setProfile";
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
var PointShadowAtlasUninitializedError = class extends Error {
|
|
288
|
+
code = "point-shadow-atlas-uninitialized";
|
|
289
|
+
expected;
|
|
290
|
+
hint;
|
|
291
|
+
constructor() {
|
|
292
|
+
const expected = "ShadowAtlas.ensure() invoked before faceView()";
|
|
293
|
+
const hint = "Gate faceView on isAllocated() or call ensure() once in the per-frame extract step before iterating face views";
|
|
294
|
+
super("ShadowAtlas.faceView called before ensure(); the cube_array texture is not allocated");
|
|
295
|
+
this.name = "PointShadowAtlasUninitializedError";
|
|
296
|
+
this.expected = expected;
|
|
297
|
+
this.hint = hint;
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
var PointShadowAtlasBoundsViolationError = class extends Error {
|
|
301
|
+
code = "point-shadow-atlas-bounds-violation";
|
|
302
|
+
expected;
|
|
303
|
+
hint;
|
|
304
|
+
detail;
|
|
305
|
+
constructor(axis, value, max) {
|
|
306
|
+
const expected = `0 <= ${axis} < ${max}`;
|
|
307
|
+
const hint = axis === "layer" ? `clamp PointLight.shadowAtlasLayer to [0, ${max}); the cap on layers equals PointLightShadow cardinality (4)` : `clamp face index to [0, ${max}); cube faces are indexed 0..5 in +X/-X/+Y/-Y/+Z/-Z order`;
|
|
308
|
+
super(`ShadowAtlas.faceView ${axis} out of range: ${value} (must be in [0, ${max}))`);
|
|
309
|
+
this.name = "PointShadowAtlasBoundsViolationError";
|
|
310
|
+
this.expected = expected;
|
|
311
|
+
this.hint = hint;
|
|
312
|
+
this.detail = { axis, value, max };
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
var VideoUploadUnsupportedError = class extends Error {
|
|
316
|
+
code = "video-upload-unsupported";
|
|
317
|
+
expected;
|
|
318
|
+
hint;
|
|
319
|
+
constructor() {
|
|
320
|
+
const expected = "at least one video upload path available: a host HTMLVideoElement (general copyExternalImageToTexture path) or GPUExternalTexture capability (high-perf path)";
|
|
321
|
+
const hint = "this backend exposes no usable video upload path; render a static texture instead, or switch to a WebGPU backend that supports video texture upload";
|
|
322
|
+
super("video upload unsupported \u2014 no general or high-perf path available");
|
|
323
|
+
this.name = "VideoUploadUnsupportedError";
|
|
324
|
+
this.expected = expected;
|
|
325
|
+
this.hint = hint;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
var VertexColorVariantConflictError = class extends Error {
|
|
329
|
+
code = "vertex-color-variant-conflict";
|
|
330
|
+
expected;
|
|
331
|
+
hint;
|
|
332
|
+
detail;
|
|
333
|
+
constructor(authoredValue, projected) {
|
|
334
|
+
const expected = `VERTEX_COLOR_AVAILABLE=${projected ? "true" : "false"}`;
|
|
335
|
+
const hint = "derive the shader variant from the mesh VertexLayoutProjection; COLOR_0 presence is a geometry fact";
|
|
336
|
+
super(`authored vertex-color variant ${authoredValue} disagrees with projected ${expected}`);
|
|
337
|
+
this.name = "VertexColorVariantConflictError";
|
|
338
|
+
this.expected = expected;
|
|
339
|
+
this.hint = hint;
|
|
340
|
+
this.detail = { authored: true, authoredValue, projected };
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
var SkinPaletteOverflowError = class extends Error {
|
|
344
|
+
code = "skin-palette-overflow";
|
|
345
|
+
expected;
|
|
346
|
+
hint;
|
|
347
|
+
detail;
|
|
348
|
+
constructor(requestedBytes, limit) {
|
|
349
|
+
const expected = `skinned joint palette (${requestedBytes} B) fits within device.limits.maxStorageBufferBindingSize (${limit} B)`;
|
|
350
|
+
const hint = "palette buffer exceeds device maxStorageBufferBindingSize; reduce skinned entity count or split into multiple palette buffers (OOS-skin-palette-batch)";
|
|
351
|
+
super(`skin palette buffer needs ${requestedBytes} B, exceeds device limit ${limit} B`);
|
|
352
|
+
this.name = "SkinPaletteOverflowError";
|
|
353
|
+
this.expected = expected;
|
|
354
|
+
this.hint = hint;
|
|
355
|
+
this.detail = { requestedBytes, limit };
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
var SkinMaterialMismatchError = class extends Error {
|
|
359
|
+
code = "skin-material-mismatch";
|
|
360
|
+
expected;
|
|
361
|
+
hint;
|
|
362
|
+
detail;
|
|
363
|
+
constructor(entity, actualShader) {
|
|
364
|
+
const expected = "Skin entity's first material program module === 'forgeax::pbr-skin'";
|
|
365
|
+
const hint = `entity ${entity} has Skin but the first material program module is ${actualShader ?? "<empty>"}; load the mesh via the gltf importer (cooker auto-routes 'forgeax::pbr-skin' for skinned primitives), or remove the Skin component to render the entity unskinned with Materials.standard / Materials.unlit`;
|
|
366
|
+
super(
|
|
367
|
+
`Skin / material mismatch on entity ${entity}: expected forgeax::pbr-skin, got ${actualShader ?? "<empty>"}`
|
|
368
|
+
);
|
|
369
|
+
this.name = "SkinMaterialMismatchError";
|
|
370
|
+
this.expected = expected;
|
|
371
|
+
this.hint = hint;
|
|
372
|
+
this.detail = { entity, actualShader };
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
var MaterialSkinAttrMissingError = class extends Error {
|
|
376
|
+
code = "material-skin-attr-missing";
|
|
377
|
+
expected;
|
|
378
|
+
hint;
|
|
379
|
+
detail;
|
|
380
|
+
constructor(entity, missing) {
|
|
381
|
+
const expected = "pbr-skin material requires mesh.attributes.skinIndex + skinWeight";
|
|
382
|
+
const hint = `entity ${entity} uses forgeax::pbr-skin but its MeshAsset is missing ${missing}; switch the entity to a skinned glTF mesh authored with JOINTS_0 + WEIGHTS_0, or change the material to a non-skin shader via Materials.standard / Materials.unlit`;
|
|
383
|
+
super(
|
|
384
|
+
`material/skin attribute mismatch on entity ${entity}: pbr-skin material with mesh missing ${missing}`
|
|
385
|
+
);
|
|
386
|
+
this.name = "MaterialSkinAttrMissingError";
|
|
387
|
+
this.expected = expected;
|
|
388
|
+
this.hint = hint;
|
|
389
|
+
this.detail = { entity, missing };
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
var TransmissionCapabilityMissingError = class extends Error {
|
|
393
|
+
code = "transmission-capability-missing";
|
|
394
|
+
expected = "the renderer exposes the transmission capability for this material";
|
|
395
|
+
hint = "disable transmission or provide the renderer capability before drawing";
|
|
396
|
+
detail;
|
|
397
|
+
constructor(material, stage, evidence) {
|
|
398
|
+
super(`transmission capability is missing for material '${material}'`);
|
|
399
|
+
this.name = "TransmissionCapabilityMissingError";
|
|
400
|
+
this.detail = { material, capability: "transmission", stage, ...evidence };
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
var renderFeatureRecoveryHintByRecovery = {
|
|
404
|
+
"next-frame": (featureIdentity, stage) => `correct '${featureIdentity}' ${stage} data and retry on the next frame`,
|
|
405
|
+
"renderer-recover": (featureIdentity, _stage) => `wait for renderer recovery before retrying '${featureIdentity}'`,
|
|
406
|
+
registration: (featureIdentity, _stage) => `correct '${featureIdentity}' registration before retrying`
|
|
407
|
+
};
|
|
408
|
+
var RenderFeatureRegistrationConflictError = class extends Error {
|
|
409
|
+
code = "render-feature-registration-conflict";
|
|
410
|
+
expected;
|
|
411
|
+
hint;
|
|
412
|
+
detail;
|
|
413
|
+
constructor(featureIdentity, order, conflictingOrder) {
|
|
414
|
+
const expected = `feature identity '${featureIdentity}' is unique`;
|
|
415
|
+
const hint = `rename '${featureIdentity}' or remove the duplicate feature before registration`;
|
|
416
|
+
super(`render feature registration conflict for '${featureIdentity}'`);
|
|
417
|
+
this.name = "RenderFeatureRegistrationConflictError";
|
|
418
|
+
this.expected = expected;
|
|
419
|
+
this.hint = hint;
|
|
420
|
+
this.detail = { featureIdentity, order, conflictingOrder };
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
var RenderFeatureStageFailedError = class extends Error {
|
|
424
|
+
code = "render-feature-stage-failed";
|
|
425
|
+
expected;
|
|
426
|
+
hint;
|
|
427
|
+
detail;
|
|
428
|
+
constructor(featureIdentity, order, stage, recovery, cause) {
|
|
429
|
+
const expected = `feature '${featureIdentity}' completes its ${stage} stage without an error`;
|
|
430
|
+
const hint = renderFeatureRecoveryHintByRecovery[recovery](featureIdentity, stage);
|
|
431
|
+
super(`render feature '${featureIdentity}' failed during ${stage}`);
|
|
432
|
+
this.name = "RenderFeatureStageFailedError";
|
|
433
|
+
this.expected = expected;
|
|
434
|
+
this.hint = hint;
|
|
435
|
+
this.detail = {
|
|
436
|
+
featureIdentity,
|
|
437
|
+
order,
|
|
438
|
+
stage,
|
|
439
|
+
recovery,
|
|
440
|
+
...cause === void 0 ? {} : { cause }
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
var RenderFeatureCapabilityMissingError = class extends Error {
|
|
445
|
+
code = "render-feature-capability-missing";
|
|
446
|
+
expected;
|
|
447
|
+
hint;
|
|
448
|
+
detail;
|
|
449
|
+
constructor(featureIdentity, order, capability) {
|
|
450
|
+
const expected = `device capability '${capability}' is available for feature '${featureIdentity}'`;
|
|
451
|
+
const hint = `disable '${featureIdentity}' or use a device with '${capability}' capability`;
|
|
452
|
+
super(`render feature '${featureIdentity}' requires missing capability '${capability}'`);
|
|
453
|
+
this.name = "RenderFeatureCapabilityMissingError";
|
|
454
|
+
this.expected = expected;
|
|
455
|
+
this.hint = hint;
|
|
456
|
+
this.detail = { featureIdentity, order, capability };
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
var RenderFeaturePreparationFailedError = class extends Error {
|
|
460
|
+
code = "render-feature-preparation-failed";
|
|
461
|
+
expected;
|
|
462
|
+
hint;
|
|
463
|
+
detail;
|
|
464
|
+
constructor(featureIdentity, order, operation, resourceKind, resourceName, reason, recovery) {
|
|
465
|
+
const expected = `${resourceKind} '${resourceName}' is prepared during ${operation}`;
|
|
466
|
+
const hint = `repair '${resourceName}' and retry feature '${featureIdentity}' on ${recovery}`;
|
|
467
|
+
super(`render feature '${featureIdentity}' preparation failed for '${resourceName}'`);
|
|
468
|
+
this.name = "RenderFeaturePreparationFailedError";
|
|
469
|
+
this.expected = expected;
|
|
470
|
+
this.hint = hint;
|
|
471
|
+
this.detail = {
|
|
472
|
+
featureIdentity,
|
|
473
|
+
order,
|
|
474
|
+
stage: "prepare",
|
|
475
|
+
operation,
|
|
476
|
+
resourceKind,
|
|
477
|
+
resourceName,
|
|
478
|
+
reason,
|
|
479
|
+
recovery
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
var RenderFeaturePreparedStateMismatchError = class extends Error {
|
|
484
|
+
code = "render-feature-prepared-state-mismatch";
|
|
485
|
+
expected;
|
|
486
|
+
hint;
|
|
487
|
+
detail;
|
|
488
|
+
constructor(detail) {
|
|
489
|
+
const expected = `${detail.resourceKind} state is compatible for '${detail.operation}'`;
|
|
490
|
+
const hint = `repair '${detail.reason}' for feature '${detail.featureIdentity}' and retry`;
|
|
491
|
+
super(`render feature '${detail.featureIdentity}' prepared state mismatch`);
|
|
492
|
+
this.name = "RenderFeaturePreparedStateMismatchError";
|
|
493
|
+
this.expected = expected;
|
|
494
|
+
this.hint = hint;
|
|
495
|
+
this.detail = detail;
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
var RenderFeatureDrawRecordingFailedError = class extends Error {
|
|
499
|
+
code = "render-feature-draw-recording-failed";
|
|
500
|
+
expected;
|
|
501
|
+
hint;
|
|
502
|
+
detail;
|
|
503
|
+
constructor(featureIdentity, order, operation, resourceKind, reason, backendReason, recovery) {
|
|
504
|
+
const expected = `${resourceKind} recording succeeds for '${operation}'`;
|
|
505
|
+
const hint = `repair '${reason}' and retry feature '${featureIdentity}' after ${recovery}`;
|
|
506
|
+
super(`render feature '${featureIdentity}' draw recording failed`);
|
|
507
|
+
this.name = "RenderFeatureDrawRecordingFailedError";
|
|
508
|
+
this.expected = expected;
|
|
509
|
+
this.hint = hint;
|
|
510
|
+
this.detail = {
|
|
511
|
+
featureIdentity,
|
|
512
|
+
order,
|
|
513
|
+
stage: "record",
|
|
514
|
+
operation,
|
|
515
|
+
resourceKind,
|
|
516
|
+
reason,
|
|
517
|
+
backendReason,
|
|
518
|
+
recovery
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
var ObservationUnavailableError = class extends Error {
|
|
523
|
+
code = "observation-unavailable";
|
|
524
|
+
expected;
|
|
525
|
+
hint;
|
|
526
|
+
detail;
|
|
527
|
+
constructor(reason, hint) {
|
|
528
|
+
let recovery;
|
|
529
|
+
if (reason === "copy-src") recovery = "enable-copy-src";
|
|
530
|
+
else if (reason === "resource" || reason === "readback-failed") recovery = "retry-readback";
|
|
531
|
+
else recovery = "draw-current-frame";
|
|
532
|
+
super(`current-frame observation unavailable: ${reason}`);
|
|
533
|
+
this.name = "ObservationUnavailableError";
|
|
534
|
+
this.expected = "a fresh producer-owned rgba16float current-frame observation";
|
|
535
|
+
this.hint = hint;
|
|
536
|
+
this.detail = { reason, recovery };
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
var SceneDataUnavailableError = class extends Error {
|
|
540
|
+
code = "scene-data-unavailable";
|
|
541
|
+
expected = "the requested semantic scene data is available for the active plan";
|
|
542
|
+
hint;
|
|
543
|
+
detail;
|
|
544
|
+
constructor(detail) {
|
|
545
|
+
const hint = detail.recovery === "enable-capability" ? "enable rgba16floatRenderable and retry the current frame" : detail.recovery === "renderer-recover" ? "wait for renderer recovery, then retry the frame" : "restore the producer coverage and retry on the next frame";
|
|
546
|
+
super(`scene data '${detail.schema}' unavailable for '${detail.featureIdentity}'`);
|
|
547
|
+
this.name = "SceneDataUnavailableError";
|
|
548
|
+
this.hint = hint;
|
|
549
|
+
this.detail = Object.freeze({
|
|
550
|
+
...detail,
|
|
551
|
+
missingContributorIds: Object.freeze([...detail.missingContributorIds].slice(0, 32)),
|
|
552
|
+
omittedMissingContributorCount: Math.max(
|
|
553
|
+
detail.omittedMissingContributorCount,
|
|
554
|
+
Math.max(0, detail.missingContributorIds.length - 32)
|
|
555
|
+
)
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
var FrameReceiptStaleError = class extends Error {
|
|
560
|
+
code = "frame-receipt-stale";
|
|
561
|
+
expected = "the observation receipt belongs to the active device generation";
|
|
562
|
+
hint = "draw a new frame and call observe with its returned FrameReceipt";
|
|
563
|
+
detail;
|
|
564
|
+
constructor(detail) {
|
|
565
|
+
super("frame receipt belongs to a retired device generation");
|
|
566
|
+
this.name = "FrameReceiptStaleError";
|
|
567
|
+
this.detail = detail;
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
var RendererContractFailureError = class extends Error {
|
|
571
|
+
code = "renderer-contract-failed";
|
|
572
|
+
expected = "renderer owner contracts remain valid at the public boundary";
|
|
573
|
+
hint = "repair the owner contract and retry the operation";
|
|
574
|
+
detail;
|
|
575
|
+
constructor(operation, cause) {
|
|
576
|
+
super(`renderer ${operation} contract failed: ${cause}`);
|
|
577
|
+
this.name = "RendererContractFailureError";
|
|
578
|
+
this.detail = { operation, cause };
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
var EnvironmentSourceConflictError = class extends Error {
|
|
582
|
+
code = "environment-source-conflict";
|
|
583
|
+
expected = "exactly one environment source owns the frame";
|
|
584
|
+
hint = "remove all but one image or atmosphere environment owner";
|
|
585
|
+
detail;
|
|
586
|
+
constructor(owners) {
|
|
587
|
+
super("environment source owners conflict");
|
|
588
|
+
this.name = "EnvironmentSourceConflictError";
|
|
589
|
+
this.detail = { owners: owners.map((owner) => Object.freeze({ ...owner })) };
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
var FogCardinalityError = class extends Error {
|
|
593
|
+
code = "fog-cardinality";
|
|
594
|
+
expected = "zero or one Fog owner contributes to a frame";
|
|
595
|
+
hint = "remove extra Fog owners so the resource owner has at most one";
|
|
596
|
+
detail;
|
|
597
|
+
constructor(count) {
|
|
598
|
+
super(`Fog owner cardinality is ${count}`);
|
|
599
|
+
this.name = "FogCardinalityError";
|
|
600
|
+
this.detail = { count };
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
var TaaCapsInsufficientError = class extends Error {
|
|
604
|
+
code = "taa-caps-insufficient";
|
|
605
|
+
expected = "the backend exposes the capabilities required by TAA";
|
|
606
|
+
hint = "select a backend with the required TAA capabilities or disable TAA on Camera";
|
|
607
|
+
detail;
|
|
608
|
+
constructor(required, available) {
|
|
609
|
+
super("TAA capabilities are insufficient");
|
|
610
|
+
this.name = "TaaCapsInsufficientError";
|
|
611
|
+
this.detail = { required: [...required], available: [...available] };
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
var EnvironmentGenerationFailedError = class extends Error {
|
|
615
|
+
code = "environment-generation-failed";
|
|
616
|
+
expected = "the selected environment generation completes its owner stage";
|
|
617
|
+
hint = "inspect the stage and sourceKey, then retry after correcting the environment";
|
|
618
|
+
detail;
|
|
619
|
+
constructor(sourceKey, stage) {
|
|
620
|
+
super(`environment generation failed during ${stage}`);
|
|
621
|
+
this.name = "EnvironmentGenerationFailedError";
|
|
622
|
+
this.detail = { sourceKey, stage };
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
var AtmosphereInvalidParameterError = class extends Error {
|
|
626
|
+
code = "atmosphere-invalid-parameter";
|
|
627
|
+
expected;
|
|
628
|
+
hint;
|
|
629
|
+
detail;
|
|
630
|
+
constructor(field, value, range) {
|
|
631
|
+
super(`Atmosphere.${field} is invalid`);
|
|
632
|
+
this.name = "AtmosphereInvalidParameterError";
|
|
633
|
+
this.detail = { field, value };
|
|
634
|
+
const rangeText = Number.isFinite(range.max) ? `[${range.min}, ${range.max}]` : `>= ${range.min}`;
|
|
635
|
+
this.expected = `Atmosphere.${field} must be finite and ${rangeText}`;
|
|
636
|
+
this.hint = `set Atmosphere.${field} to a finite value ${rangeText}`;
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
var DynamicResolutionInvalidParameterError = class extends Error {
|
|
640
|
+
code = "dynamic-resolution-invalid-parameter";
|
|
641
|
+
expected;
|
|
642
|
+
hint;
|
|
643
|
+
detail;
|
|
644
|
+
constructor(detail) {
|
|
645
|
+
super(`DynamicResolution.${detail.field} is invalid`);
|
|
646
|
+
this.name = "DynamicResolutionInvalidParameterError";
|
|
647
|
+
this.expected = `DynamicResolution.${detail.field} must be ${detail.expected}`;
|
|
648
|
+
this.hint = `set DynamicResolution.${detail.field} to a value that is ${detail.expected}`;
|
|
649
|
+
this.detail = detail;
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
var DynamicResolutionRequiresTaaError = class extends Error {
|
|
653
|
+
code = "dynamic-resolution-requires-taa";
|
|
654
|
+
expected = "DynamicResolution requires Camera.antialias to be 'taa'";
|
|
655
|
+
hint = "set Camera.antialias to 'taa' or remove DynamicResolution before retrying";
|
|
656
|
+
detail;
|
|
657
|
+
constructor(detail) {
|
|
658
|
+
super("DynamicResolution requires TAA");
|
|
659
|
+
this.name = "DynamicResolutionRequiresTaaError";
|
|
660
|
+
this.detail = detail;
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
var DynamicResolutionTimingUnavailableError = class extends Error {
|
|
664
|
+
code = "dynamic-resolution-timing-unavailable";
|
|
665
|
+
expected = "adaptive resolution receives a completed GPU timing sample";
|
|
666
|
+
hint = "use fixed minScale=maxScale or retry after timestamp support is available";
|
|
667
|
+
detail;
|
|
668
|
+
constructor(detail) {
|
|
669
|
+
super(`DynamicResolution timing is unavailable for generation ${detail.generation}`);
|
|
670
|
+
this.name = "DynamicResolutionTimingUnavailableError";
|
|
671
|
+
this.detail = detail;
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
var BarrelDistortionInvalidParameterError = class extends Error {
|
|
675
|
+
code = "barrel-distortion-invalid-parameter";
|
|
676
|
+
expected;
|
|
677
|
+
hint;
|
|
678
|
+
detail;
|
|
679
|
+
constructor(detail) {
|
|
680
|
+
super(`BarrelDistortion.${detail.field} is invalid`);
|
|
681
|
+
this.name = "BarrelDistortionInvalidParameterError";
|
|
682
|
+
this.expected = `BarrelDistortion.${detail.field} must be ${detail.expected}`;
|
|
683
|
+
this.hint = `set BarrelDistortion.${detail.field} to a value that is ${detail.expected}`;
|
|
684
|
+
this.detail = detail;
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
var OwnerStageFailedError = class extends Error {
|
|
688
|
+
code = "owner-stage-failed";
|
|
689
|
+
expected = "the owner completes its current frame stage";
|
|
690
|
+
hint = "inspect the owner and stage, keep the last-known-good frame, and retry";
|
|
691
|
+
detail;
|
|
692
|
+
constructor(owner, stage) {
|
|
693
|
+
super(`${owner} owner failed during ${stage}`);
|
|
694
|
+
this.name = "OwnerStageFailedError";
|
|
695
|
+
this.detail = { owner, stage };
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
var RENDERER_OPERATION_ERROR_POLICY = {
|
|
699
|
+
"world-lease-invalid": {
|
|
700
|
+
expected: "every render World is represented by a live lease owned by this Renderer",
|
|
701
|
+
hint: "attach the World to this Renderer and use the returned lease"
|
|
702
|
+
},
|
|
703
|
+
"frame-input-invalid": {
|
|
704
|
+
expected: "the frame input references attached leases and a valid immutable RenderProfile",
|
|
705
|
+
hint: "repair the frame input and retry draw or setProfile"
|
|
706
|
+
},
|
|
707
|
+
"scene-projection-failed": {
|
|
708
|
+
expected: "the attached World projects into the renderer-owned RenderScene",
|
|
709
|
+
hint: "inspect the structured cause, repair the World publication, and retry draw"
|
|
710
|
+
},
|
|
711
|
+
"asset-binding-failed": {
|
|
712
|
+
expected: "all frame assets resolve to valid renderer-owned bindings",
|
|
713
|
+
hint: "inspect the structured cause, rebuild or cold-cook the asset, and retry draw"
|
|
714
|
+
},
|
|
715
|
+
"feature-plan-failed": {
|
|
716
|
+
expected: "every installed RenderFeature produces a valid declarative plan",
|
|
717
|
+
hint: "inspect the feature cause, repair its plan, and retry draw"
|
|
718
|
+
},
|
|
719
|
+
"graph-build-failed": {
|
|
720
|
+
expected: "the Standard graph builds from the active profile and feature plans",
|
|
721
|
+
hint: "inspect the graph cause, repair the profile or plan, and retry"
|
|
722
|
+
},
|
|
723
|
+
"device-operation-failed": {
|
|
724
|
+
expected: "the active device generation completes the renderer-owned operation",
|
|
725
|
+
hint: "inspect renderer state and the structured cause, then retry or recover"
|
|
726
|
+
},
|
|
727
|
+
"surface-unavailable": {
|
|
728
|
+
expected: "the presentation surface accepts the requested lifecycle operation",
|
|
729
|
+
hint: "inspect renderer state, then restore the surface or create a new Renderer"
|
|
730
|
+
},
|
|
731
|
+
"renderer-state-invalid": {
|
|
732
|
+
expected: "the Renderer is in a state that accepts the requested operation",
|
|
733
|
+
hint: "inspect renderer state and choose retry, restoreSurface, recover, or stop"
|
|
734
|
+
},
|
|
735
|
+
"recovery-failed": {
|
|
736
|
+
expected: "one recovery attempt publishes a complete replacement device generation",
|
|
737
|
+
hint: "inspect the structured cause and retry recover after the host-selected delay"
|
|
738
|
+
},
|
|
739
|
+
"cleanup-failed": {
|
|
740
|
+
expected: "Renderer disposal completes every registered cleanup in reverse ownership order",
|
|
741
|
+
hint: "inspect the ordered cleanup causes; the Renderer remains disposed and must not be reused"
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
var RendererOperationError = class extends Error {
|
|
745
|
+
code;
|
|
746
|
+
expected;
|
|
747
|
+
hint;
|
|
748
|
+
detail;
|
|
749
|
+
constructor(code, detail) {
|
|
750
|
+
const policy = RENDERER_OPERATION_ERROR_POLICY[code];
|
|
751
|
+
super(`${code}: ${policy.expected}`);
|
|
752
|
+
this.name = "RendererOperationError";
|
|
753
|
+
this.code = code;
|
|
754
|
+
this.expected = policy.expected;
|
|
755
|
+
this.hint = policy.hint;
|
|
756
|
+
this.detail = detail;
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
var PointsLinesInvalidStyleError = class extends Error {
|
|
760
|
+
code = "points-lines-invalid-style";
|
|
761
|
+
expected;
|
|
762
|
+
hint;
|
|
763
|
+
detail;
|
|
764
|
+
constructor(detail) {
|
|
765
|
+
super(`invalid ${detail.component} style at ${detail.field}`);
|
|
766
|
+
this.name = "PointsLinesInvalidStyleError";
|
|
767
|
+
this.expected = detail.expected;
|
|
768
|
+
this.hint = `repair entity ${detail.entity} ${detail.component}.${detail.field} and retry admission`;
|
|
769
|
+
this.detail = detail;
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
var PointsLinesTopologyMismatchError = class extends Error {
|
|
773
|
+
code = "points-lines-topology-mismatch";
|
|
774
|
+
expected;
|
|
775
|
+
hint;
|
|
776
|
+
detail;
|
|
777
|
+
constructor(detail) {
|
|
778
|
+
super(`Points/Lines topology mismatch at submesh ${detail.submesh}`);
|
|
779
|
+
this.name = "PointsLinesTopologyMismatchError";
|
|
780
|
+
this.expected = `submesh ${detail.submesh} topology is ${detail.expected}`;
|
|
781
|
+
this.hint = `rebuild entity ${detail.entity} with ${detail.expected} geometry before retrying Points/Lines admission`;
|
|
782
|
+
this.detail = detail;
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
var PointsLinesStyleUnsupportedError = class extends Error {
|
|
786
|
+
code = "points-lines-style-unsupported";
|
|
787
|
+
expected;
|
|
788
|
+
hint;
|
|
789
|
+
detail;
|
|
790
|
+
constructor(detail) {
|
|
791
|
+
super(`unsupported Points/Lines ${detail.field} member ${detail.member}`);
|
|
792
|
+
this.name = "PointsLinesStyleUnsupportedError";
|
|
793
|
+
this.expected = `${detail.field} is one of ${detail.supported.join(", ")}`;
|
|
794
|
+
this.hint = `use a supported Points/Lines ${detail.field} member or wait for a later milestone`;
|
|
795
|
+
this.detail = detail;
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
var PointsLinesMaterialUnsupportedError = class extends Error {
|
|
799
|
+
code = "points-lines-material-unsupported";
|
|
800
|
+
expected = "one engine-owned unlit forward MaterialAsset pass";
|
|
801
|
+
hint;
|
|
802
|
+
detail;
|
|
803
|
+
constructor(detail) {
|
|
804
|
+
super(`Points/Lines material is unsupported on entity ${detail.entity}`);
|
|
805
|
+
this.name = "PointsLinesMaterialUnsupportedError";
|
|
806
|
+
this.hint = `use Materials.unlit without a shadow-caster pass for entity ${detail.entity}`;
|
|
807
|
+
this.detail = detail;
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
var PointsLinesBudgetExceededError = class extends Error {
|
|
811
|
+
code = "points-lines-budget-exceeded";
|
|
812
|
+
expected;
|
|
813
|
+
hint;
|
|
814
|
+
detail;
|
|
815
|
+
constructor(detail) {
|
|
816
|
+
super(`Points/Lines ${detail.unit} budget exceeded`);
|
|
817
|
+
this.name = "PointsLinesBudgetExceededError";
|
|
818
|
+
this.expected = `${detail.unit} <= ${detail.limit}`;
|
|
819
|
+
this.hint = `reduce Points/Lines ${detail.unit} or split the entity into bounded equivalent batches`;
|
|
820
|
+
this.detail = detail;
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
var PointsLinesPrepareFailedError = class extends Error {
|
|
824
|
+
code = "points-lines-prepare-failed";
|
|
825
|
+
expected = "the complete Points/Lines candidate validates before publication";
|
|
826
|
+
hint;
|
|
827
|
+
detail;
|
|
828
|
+
constructor(detail) {
|
|
829
|
+
super(`Points/Lines prepare failed at generation ${detail.generation}`);
|
|
830
|
+
this.name = "PointsLinesPrepareFailedError";
|
|
831
|
+
this.hint = detail.lastKnownGood ? "retain the last known good candidate, repair the producer, and retry prepare" : "repair the producer and retry prepare; the failed first candidate produces zero draw";
|
|
832
|
+
this.detail = detail;
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
var RenderTargetDescriptorInvalidError = class extends Error {
|
|
836
|
+
code = "render-target-descriptor-invalid";
|
|
837
|
+
expected;
|
|
838
|
+
hint;
|
|
839
|
+
detail;
|
|
840
|
+
constructor(detail) {
|
|
841
|
+
super(`render-target-descriptor-invalid: ${detail.field} does not satisfy ${detail.expected}`);
|
|
842
|
+
this.name = "RenderTargetDescriptorInvalidError";
|
|
843
|
+
this.expected = detail.expected;
|
|
844
|
+
this.hint = `set RenderTargetDescriptor.${detail.field} to the expected value, then retry create or resize`;
|
|
845
|
+
this.detail = detail;
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
var RenderTargetCapabilityMissingError = class extends Error {
|
|
849
|
+
code = "render-target-capability-missing";
|
|
850
|
+
expected;
|
|
851
|
+
hint;
|
|
852
|
+
detail;
|
|
853
|
+
constructor(detail) {
|
|
854
|
+
super(
|
|
855
|
+
`render-target-capability-missing: ${detail.capability} does not admit ${detail.requested}`
|
|
856
|
+
);
|
|
857
|
+
this.name = "RenderTargetCapabilityMissingError";
|
|
858
|
+
this.expected = `${detail.capability} admits ${detail.requested}`;
|
|
859
|
+
this.hint = `choose an admitted target descriptor or use a backend providing ${detail.capability}`;
|
|
860
|
+
this.detail = detail;
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
var RenderTargetStateInvalidError = class extends Error {
|
|
864
|
+
code = "render-target-state-invalid";
|
|
865
|
+
expected;
|
|
866
|
+
hint;
|
|
867
|
+
detail;
|
|
868
|
+
constructor(detail) {
|
|
869
|
+
super(`render-target-state-invalid: ${detail.operation} cannot use ${detail.reason}`);
|
|
870
|
+
this.name = "RenderTargetStateInvalidError";
|
|
871
|
+
this.expected = `target state permits ${detail.operation}`;
|
|
872
|
+
this.hint = "use the Renderer that created the target, then initialize, recover, or stop using the destroyed token";
|
|
873
|
+
this.detail = detail;
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
var RenderTargetOperationFailedError = class extends Error {
|
|
877
|
+
code = "render-target-operation-failed";
|
|
878
|
+
expected;
|
|
879
|
+
hint;
|
|
880
|
+
detail;
|
|
881
|
+
constructor(detail) {
|
|
882
|
+
super(`render-target-operation-failed: ${detail.operation} failed during ${detail.stage}`);
|
|
883
|
+
this.name = "RenderTargetOperationFailedError";
|
|
884
|
+
this.expected = `${detail.operation} completes ${detail.stage}`;
|
|
885
|
+
this.hint = "inspect detail.cause, then retry, recover the Renderer, or retain the last-known-good generation";
|
|
886
|
+
this.detail = detail;
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
var RenderIntentInvalidError = class extends Error {
|
|
890
|
+
code = "render-intent-invalid";
|
|
891
|
+
expected;
|
|
892
|
+
hint;
|
|
893
|
+
detail;
|
|
894
|
+
constructor(component, value) {
|
|
895
|
+
super(`render-intent-invalid: ${component}.updateIntent is not an admitted value`);
|
|
896
|
+
this.name = "RenderIntentInvalidError";
|
|
897
|
+
this.expected = `${component}.updateIntent is one of 0, 1, or 2`;
|
|
898
|
+
this.hint = `set ${component}.updateIntent to 0, 1, or 2`;
|
|
899
|
+
this.detail = { component, field: "updateIntent", value, allowed: [0, 1, 2] };
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
var VolumeOwnerConflictError = class extends Error {
|
|
903
|
+
code = "volume-owner-conflict";
|
|
904
|
+
expected = "at most eight local VolumetricFog owners per rendered World";
|
|
905
|
+
hint = "reduce simultaneously visible volume owners and retry extraction";
|
|
906
|
+
detail;
|
|
907
|
+
constructor(ownerCount) {
|
|
908
|
+
super(`volume-owner-conflict: received ${ownerCount} owners`);
|
|
909
|
+
this.name = "VolumeOwnerConflictError";
|
|
910
|
+
this.detail = { ownerCount };
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
var VolumeDensityShapeMismatchError = class extends Error {
|
|
914
|
+
code = "volume-density-shape-mismatch";
|
|
915
|
+
expected = "density is a linear 3D TextureAsset";
|
|
916
|
+
hint = "bind a verified linear texture with viewDimension 3d";
|
|
917
|
+
detail;
|
|
918
|
+
constructor(guid, viewDimension) {
|
|
919
|
+
super(`volume-density-shape-mismatch: ${viewDimension} density is not 3d`);
|
|
920
|
+
this.name = "VolumeDensityShapeMismatchError";
|
|
921
|
+
this.detail = { guid, viewDimension };
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
var VolumeInvalidBoundsError = class extends Error {
|
|
925
|
+
code = "volume-invalid-bounds";
|
|
926
|
+
expected = "bounds are finite and max is greater than min on every axis";
|
|
927
|
+
hint = "set finite non-degenerate volume bounds";
|
|
928
|
+
detail;
|
|
929
|
+
constructor(bounds) {
|
|
930
|
+
super("volume-invalid-bounds: bounds must be finite and non-degenerate");
|
|
931
|
+
this.name = "VolumeInvalidBoundsError";
|
|
932
|
+
this.detail = bounds;
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
var VolumeInvalidParametersError = class extends Error {
|
|
936
|
+
code = "volume-invalid-parameters";
|
|
937
|
+
expected = "volume parameters remain finite and inside their closed ranges";
|
|
938
|
+
hint = "repair extinction, albedo, emission, anisotropy, maxDistance, or sampling";
|
|
939
|
+
detail;
|
|
940
|
+
constructor(input) {
|
|
941
|
+
const invalidSampling = input.sampling !== void 0 && input.sampling !== "noise" && input.sampling !== "density";
|
|
942
|
+
const field = invalidSampling ? "sampling" : input.maxDistance !== void 0 && input.maxDistance <= 0 ? "maxDistance" : "parameters";
|
|
943
|
+
const value = invalidSampling ? input.sampling : field === "maxDistance" ? input.maxDistance : input.anisotropy;
|
|
944
|
+
super(`volume-invalid-parameters: ${field} is outside the authored range`);
|
|
945
|
+
this.name = "VolumeInvalidParametersError";
|
|
946
|
+
this.detail = { field, value };
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
var MOTION_BLUR_PARAMS_BYTE_SIZE = 32;
|
|
950
|
+
var DEFAULT_MOTION_BLUR_PARAMS = Object.freeze({
|
|
951
|
+
shutterAngle: 180,
|
|
952
|
+
maxRadiusPixels: 32,
|
|
953
|
+
sampleCount: 8,
|
|
954
|
+
targetFps: 60
|
|
955
|
+
});
|
|
956
|
+
var MotionBlurValidationError = class extends Error {
|
|
957
|
+
code = "motion-blur-invalid-params";
|
|
958
|
+
expected;
|
|
959
|
+
hint;
|
|
960
|
+
detail;
|
|
961
|
+
constructor(detail) {
|
|
962
|
+
const integer = detail.integer === true ? "integer " : "";
|
|
963
|
+
const expected = `${detail.field} ${integer}in [${detail.min}, ${detail.max}]`;
|
|
964
|
+
super(`motion-blur-invalid-params: ${expected}`);
|
|
965
|
+
this.name = "MotionBlurValidationError";
|
|
966
|
+
this.expected = expected;
|
|
967
|
+
this.hint = `set ${detail.field} to an ${integer}value in [${detail.min}, ${detail.max}]`;
|
|
968
|
+
this.detail = detail;
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
function validateField(field, value, min, max, integer = false) {
|
|
972
|
+
if (!Number.isFinite(value) || value < min || value > max || integer && !Number.isInteger(value)) {
|
|
973
|
+
return new MotionBlurValidationError({
|
|
974
|
+
field,
|
|
975
|
+
value,
|
|
976
|
+
min,
|
|
977
|
+
max,
|
|
978
|
+
...integer ? { integer } : {}
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
return void 0;
|
|
982
|
+
}
|
|
983
|
+
function validateMotionBlurParams(input) {
|
|
984
|
+
const value = input ?? {};
|
|
985
|
+
const shutterAngle = value.shutterAngle ?? DEFAULT_MOTION_BLUR_PARAMS.shutterAngle;
|
|
986
|
+
const maxRadiusPixels = value.maxRadiusPixels ?? DEFAULT_MOTION_BLUR_PARAMS.maxRadiusPixels;
|
|
987
|
+
const sampleCount = value.sampleCount ?? DEFAULT_MOTION_BLUR_PARAMS.sampleCount;
|
|
988
|
+
const targetFps = value.targetFps ?? DEFAULT_MOTION_BLUR_PARAMS.targetFps;
|
|
989
|
+
const shutterError = validateField("shutterAngle", shutterAngle, 0, 360);
|
|
990
|
+
if (shutterError !== void 0) return err(shutterError);
|
|
991
|
+
const radiusError = validateField("maxRadiusPixels", maxRadiusPixels, 0, 64);
|
|
992
|
+
if (radiusError !== void 0) return err(radiusError);
|
|
993
|
+
const sampleError = validateField("sampleCount", sampleCount, 4, 16, true);
|
|
994
|
+
if (sampleError !== void 0) return err(sampleError);
|
|
995
|
+
const targetFpsError = validateField("targetFps", targetFps, 0, 240, true);
|
|
996
|
+
if (targetFpsError !== void 0) return err(targetFpsError);
|
|
997
|
+
return ok(Object.freeze({ shutterAngle, maxRadiusPixels, sampleCount, targetFps }));
|
|
998
|
+
}
|
|
999
|
+
function motionBlurTemporalDemand(params) {
|
|
1000
|
+
return params !== void 0 && params.shutterAngle > 0 && params.maxRadiusPixels > 0;
|
|
1001
|
+
}
|
|
1002
|
+
function effectiveMotionBlurSampleCount(sampleCount) {
|
|
1003
|
+
if (!Number.isFinite(sampleCount) || sampleCount < 4) return 0;
|
|
1004
|
+
if (sampleCount < 8) return 4;
|
|
1005
|
+
if (sampleCount < 16) return 8;
|
|
1006
|
+
return 16;
|
|
1007
|
+
}
|
|
1008
|
+
function isMotionBlurIntervalValid(frameDeltaSeconds) {
|
|
1009
|
+
return Number.isFinite(frameDeltaSeconds) && frameDeltaSeconds > 0 && frameDeltaSeconds <= 0.1;
|
|
1010
|
+
}
|
|
1011
|
+
function motionBlurExposureScale(frameDeltaSeconds, targetFps) {
|
|
1012
|
+
if (!isMotionBlurIntervalValid(frameDeltaSeconds)) return 0;
|
|
1013
|
+
if (!Number.isFinite(targetFps) || targetFps < 0 || targetFps > 240 || !Number.isInteger(targetFps)) {
|
|
1014
|
+
return 0;
|
|
1015
|
+
}
|
|
1016
|
+
if (targetFps === 0) return 1;
|
|
1017
|
+
return 1 / (targetFps * frameDeltaSeconds);
|
|
1018
|
+
}
|
|
1019
|
+
function motionBlurSampleDelta(sampleTimeSeconds, previousSampleTimeSeconds, fallbackDeltaSeconds) {
|
|
1020
|
+
if (sampleTimeSeconds !== void 0 && !Number.isFinite(sampleTimeSeconds) || previousSampleTimeSeconds !== void 0 && !Number.isFinite(previousSampleTimeSeconds)) {
|
|
1021
|
+
return Number.NaN;
|
|
1022
|
+
}
|
|
1023
|
+
if (Number.isFinite(sampleTimeSeconds) && Number.isFinite(previousSampleTimeSeconds)) {
|
|
1024
|
+
return sampleTimeSeconds - previousSampleTimeSeconds;
|
|
1025
|
+
}
|
|
1026
|
+
return fallbackDeltaSeconds;
|
|
1027
|
+
}
|
|
1028
|
+
function resolveMotionBlurParams(input) {
|
|
1029
|
+
if (input === void 0) return ok(void 0);
|
|
1030
|
+
return validateMotionBlurParams(input);
|
|
1031
|
+
}
|
|
1032
|
+
var DeviceResourceRef = class {
|
|
1033
|
+
kind;
|
|
1034
|
+
owner;
|
|
1035
|
+
generation;
|
|
1036
|
+
value;
|
|
1037
|
+
constructor(kind, owner, generation, value) {
|
|
1038
|
+
this.kind = kind;
|
|
1039
|
+
this.owner = owner;
|
|
1040
|
+
this.generation = generation;
|
|
1041
|
+
this.value = value;
|
|
1042
|
+
}
|
|
1043
|
+
isCurrent(scope) {
|
|
1044
|
+
return scope.accepts(this);
|
|
1045
|
+
}
|
|
1046
|
+
isStale(scope) {
|
|
1047
|
+
return !this.isCurrent(scope);
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
function idempotentCleanup(cleanup) {
|
|
1051
|
+
let cleaned = false;
|
|
1052
|
+
return (value) => {
|
|
1053
|
+
if (cleaned) return;
|
|
1054
|
+
cleaned = true;
|
|
1055
|
+
return cleanup(value);
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
var DeviceScope = class _DeviceScope {
|
|
1059
|
+
generation;
|
|
1060
|
+
owner;
|
|
1061
|
+
parent;
|
|
1062
|
+
lifecycleState = "active";
|
|
1063
|
+
resources = /* @__PURE__ */ new Map();
|
|
1064
|
+
children = [];
|
|
1065
|
+
constructor(generation, owner, parent) {
|
|
1066
|
+
this.generation = generation;
|
|
1067
|
+
this.owner = owner;
|
|
1068
|
+
this.parent = parent;
|
|
1069
|
+
parent?.children.push(this);
|
|
1070
|
+
}
|
|
1071
|
+
static create(generation, owner) {
|
|
1072
|
+
if (!Number.isSafeInteger(generation) || generation < 0) {
|
|
1073
|
+
throw new RangeError("DeviceScope generation must be a non-negative safe integer.");
|
|
1074
|
+
}
|
|
1075
|
+
if (owner.length === 0) throw new TypeError("DeviceScope owner must not be empty.");
|
|
1076
|
+
return new _DeviceScope(generation, owner);
|
|
1077
|
+
}
|
|
1078
|
+
get state() {
|
|
1079
|
+
return this.lifecycleState;
|
|
1080
|
+
}
|
|
1081
|
+
get childrenSnapshot() {
|
|
1082
|
+
return [...this.children];
|
|
1083
|
+
}
|
|
1084
|
+
/** Create a renderer-owned child scope without exposing a second device owner. */
|
|
1085
|
+
createChild(owner) {
|
|
1086
|
+
if (this.lifecycleState !== "active") {
|
|
1087
|
+
throw new Error("Cannot create a child DeviceScope from an inactive scope.");
|
|
1088
|
+
}
|
|
1089
|
+
if (owner.length === 0) throw new TypeError("DeviceScope child owner must not be empty.");
|
|
1090
|
+
return new _DeviceScope(this.generation, owner, this);
|
|
1091
|
+
}
|
|
1092
|
+
ref(kind, value) {
|
|
1093
|
+
const ref = new DeviceResourceRef(kind, this.owner, this.generation, value);
|
|
1094
|
+
this.resources.set(ref, { ref, cleanup: () => void 0 });
|
|
1095
|
+
return ref;
|
|
1096
|
+
}
|
|
1097
|
+
accepts(ref) {
|
|
1098
|
+
return this.lifecycleState === "active" && ref.owner === this.owner && ref.generation === this.generation;
|
|
1099
|
+
}
|
|
1100
|
+
isAlive() {
|
|
1101
|
+
return this.lifecycleState === "active";
|
|
1102
|
+
}
|
|
1103
|
+
resourceDelta() {
|
|
1104
|
+
return this.resources.size;
|
|
1105
|
+
}
|
|
1106
|
+
/** @internal */
|
|
1107
|
+
_adopt(kind, value, cleanup) {
|
|
1108
|
+
const ref = new DeviceResourceRef(kind, this.owner, this.generation, value);
|
|
1109
|
+
this.resources.set(ref, {
|
|
1110
|
+
ref,
|
|
1111
|
+
cleanup: idempotentCleanup(cleanup)
|
|
1112
|
+
});
|
|
1113
|
+
return ref;
|
|
1114
|
+
}
|
|
1115
|
+
/** @internal Remove ownership only after the resource's cleanup succeeded. */
|
|
1116
|
+
_release(ref) {
|
|
1117
|
+
this.resources.delete(ref);
|
|
1118
|
+
}
|
|
1119
|
+
/** @internal */
|
|
1120
|
+
_clearResources() {
|
|
1121
|
+
const resources = [...this.resources.values()];
|
|
1122
|
+
this.resources.clear();
|
|
1123
|
+
for (const resource of resources.reverse()) {
|
|
1124
|
+
try {
|
|
1125
|
+
const pending = resource.cleanup(resource.ref.value);
|
|
1126
|
+
if (pending instanceof Promise) void pending.catch(() => void 0);
|
|
1127
|
+
} catch {
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
return resources;
|
|
1131
|
+
}
|
|
1132
|
+
/** Mark an active child as retiring without releasing in-flight resources. */
|
|
1133
|
+
beginRetire() {
|
|
1134
|
+
if (this.lifecycleState === "active") this.lifecycleState = "retiring";
|
|
1135
|
+
}
|
|
1136
|
+
clearChildren() {
|
|
1137
|
+
for (const child of [...this.children].reverse()) {
|
|
1138
|
+
child.retire();
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
detachChild(child) {
|
|
1142
|
+
const index = this.children.indexOf(child);
|
|
1143
|
+
if (index >= 0) this.children.splice(index, 1);
|
|
1144
|
+
}
|
|
1145
|
+
retire() {
|
|
1146
|
+
if (this.lifecycleState !== "active" && this.lifecycleState !== "retiring") return;
|
|
1147
|
+
this.lifecycleState = "retiring";
|
|
1148
|
+
this.clearChildren();
|
|
1149
|
+
this._clearResources();
|
|
1150
|
+
this.lifecycleState = "retired";
|
|
1151
|
+
}
|
|
1152
|
+
abandon() {
|
|
1153
|
+
if (this.lifecycleState !== "active") return;
|
|
1154
|
+
this.lifecycleState = "abandoned";
|
|
1155
|
+
this.clearChildren();
|
|
1156
|
+
this._clearResources();
|
|
1157
|
+
}
|
|
1158
|
+
dispose() {
|
|
1159
|
+
if (this.lifecycleState === "disposed") return;
|
|
1160
|
+
this.lifecycleState = "disposed";
|
|
1161
|
+
this.clearChildren();
|
|
1162
|
+
this._clearResources();
|
|
1163
|
+
}
|
|
1164
|
+
async replace(generation, resources) {
|
|
1165
|
+
const replacement = new _DeviceScope(generation, this.owner, this);
|
|
1166
|
+
const transaction = new LifecycleTransaction(replacement);
|
|
1167
|
+
for (const resource of resources) transaction.add(resource);
|
|
1168
|
+
const result = await transaction.commit();
|
|
1169
|
+
if (!result.ok) {
|
|
1170
|
+
replacement.abandon();
|
|
1171
|
+
return result;
|
|
1172
|
+
}
|
|
1173
|
+
if (!this.isAlive()) {
|
|
1174
|
+
replacement.dispose();
|
|
1175
|
+
return transaction.failure("dispose");
|
|
1176
|
+
}
|
|
1177
|
+
this.detachChild(replacement);
|
|
1178
|
+
this.retire();
|
|
1179
|
+
return ok(replacement);
|
|
1180
|
+
}
|
|
1181
|
+
/** @internal */
|
|
1182
|
+
_receipt() {
|
|
1183
|
+
return {
|
|
1184
|
+
owner: this.owner,
|
|
1185
|
+
generation: this.generation,
|
|
1186
|
+
resourceCount: this.resources.size
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
var LifecycleTransaction = class {
|
|
1191
|
+
constructor(scope, options = {}) {
|
|
1192
|
+
this.scope = scope;
|
|
1193
|
+
this.options = options;
|
|
1194
|
+
}
|
|
1195
|
+
scope;
|
|
1196
|
+
resources = [];
|
|
1197
|
+
options;
|
|
1198
|
+
committed = false;
|
|
1199
|
+
add(spec) {
|
|
1200
|
+
if (this.committed) throw new Error("LifecycleTransaction is already committed.");
|
|
1201
|
+
this.resources.push(spec);
|
|
1202
|
+
return this;
|
|
1203
|
+
}
|
|
1204
|
+
async commit() {
|
|
1205
|
+
if (this.committed) return this.failure("create");
|
|
1206
|
+
this.committed = true;
|
|
1207
|
+
const created = [];
|
|
1208
|
+
for (let index = 0; index < this.resources.length; index += 1) {
|
|
1209
|
+
const spec = this.resources[index];
|
|
1210
|
+
if (spec === void 0) continue;
|
|
1211
|
+
try {
|
|
1212
|
+
if (this.options.failureAt === index + 1) {
|
|
1213
|
+
throw new Error(`injected lifecycle failure at ${index + 1}`);
|
|
1214
|
+
}
|
|
1215
|
+
const value = await spec.create();
|
|
1216
|
+
if (!this.scope.isAlive()) {
|
|
1217
|
+
await this.cleanupOne(value, created, idempotentCleanup(spec.cleanup));
|
|
1218
|
+
return this.failure("dispose");
|
|
1219
|
+
}
|
|
1220
|
+
created.push({ spec, value, cleanup: idempotentCleanup(spec.cleanup) });
|
|
1221
|
+
} catch (cause) {
|
|
1222
|
+
const cleanupFailures = await this.cleanupCreated(created);
|
|
1223
|
+
return this.failure("create", spec.kind, cleanupFailures, cause);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
if (!this.scope.isAlive()) {
|
|
1227
|
+
const cleanupFailures = await this.cleanupCreated(created);
|
|
1228
|
+
return this.failure("dispose", this.resources.at(-1)?.kind ?? "listener", cleanupFailures);
|
|
1229
|
+
}
|
|
1230
|
+
for (const item of created) this.scope._adopt(item.spec.kind, item.value, item.spec.cleanup);
|
|
1231
|
+
return ok(this.scope);
|
|
1232
|
+
}
|
|
1233
|
+
failure(operation, resourceKind = this.resources.at(-1)?.kind ?? "listener", cleanupFailures = [], cause = void 0) {
|
|
1234
|
+
return err({
|
|
1235
|
+
primary: new LifecycleConstructionError({
|
|
1236
|
+
owner: this.scope.owner,
|
|
1237
|
+
generation: this.scope.generation,
|
|
1238
|
+
operation,
|
|
1239
|
+
resourceKind,
|
|
1240
|
+
cause,
|
|
1241
|
+
cleanupFailures,
|
|
1242
|
+
receipt: this.scope._receipt()
|
|
1243
|
+
}),
|
|
1244
|
+
cleanupFailures,
|
|
1245
|
+
receipt: this.scope._receipt()
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
async cleanupCreated(created) {
|
|
1249
|
+
const failures = [];
|
|
1250
|
+
for (let index = created.length - 1; index >= 0; index -= 1) {
|
|
1251
|
+
const item = created[index];
|
|
1252
|
+
if (item === void 0) continue;
|
|
1253
|
+
try {
|
|
1254
|
+
await item.cleanup(item.value);
|
|
1255
|
+
} catch (cause) {
|
|
1256
|
+
failures.push({ resourceKind: item.spec.kind, cause });
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
return failures;
|
|
1260
|
+
}
|
|
1261
|
+
async cleanupOne(value, created, cleanup) {
|
|
1262
|
+
await this.cleanupCreated(created);
|
|
1263
|
+
try {
|
|
1264
|
+
await cleanup(value);
|
|
1265
|
+
} catch {
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
// src/gpu-texture-usage.ts
|
|
1271
|
+
var GPU_TEXTURE_USAGE_COPY_SRC = 1;
|
|
1272
|
+
var GPU_TEXTURE_USAGE_COPY_DST = 2;
|
|
1273
|
+
var GPU_TEXTURE_USAGE_TEXTURE_BINDING = 4;
|
|
1274
|
+
var GPU_TEXTURE_USAGE_STORAGE_BINDING = 8;
|
|
1275
|
+
var GPU_TEXTURE_USAGE_RENDER_ATTACHMENT = 16;
|
|
1276
|
+
var GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING = GPU_TEXTURE_USAGE_RENDER_ATTACHMENT | GPU_TEXTURE_USAGE_TEXTURE_BINDING;
|
|
1277
|
+
|
|
1278
|
+
// src/gpu-usage.ts
|
|
1279
|
+
var GPU_BUFFER_USAGE_VERTEX = 32;
|
|
1280
|
+
var GPU_BUFFER_USAGE_INDEX = 16;
|
|
1281
|
+
var GPU_BUFFER_USAGE_COPY_DST = 8;
|
|
1282
|
+
var GPU_BUFFER_USAGE_COPY_SRC = 4;
|
|
1283
|
+
var GPU_BUFFER_USAGE_UNIFORM = 64;
|
|
1284
|
+
var GPU_BUFFER_USAGE_STORAGE = 128;
|
|
1285
|
+
var GPU_BUFFER_USAGE_INDIRECT = 256;
|
|
1286
|
+
var GPU_BUFFER_USAGE_MAP_READ = 1;
|
|
1287
|
+
var GPU_BUFFER_USAGE_QUERY_RESOLVE = 512;
|
|
1288
|
+
|
|
1289
|
+
// src/prepare/extended-lighting/resources.ts
|
|
1290
|
+
var EXTENDED_LIGHTING_TOPOLOGY = "extendedLighting";
|
|
1291
|
+
var IES_SLICE_CAPACITY = 32;
|
|
1292
|
+
var COOKIE_SLICE_CAPACITY = 32;
|
|
1293
|
+
var IES_SLICE_WIDTH = 256;
|
|
1294
|
+
var IES_SLICE_HEIGHT = 128;
|
|
1295
|
+
var COOKIE_SLICE_SIZE = 256;
|
|
1296
|
+
var COOKIE_MATRIX_BYTES = 32 * 16 * Float32Array.BYTES_PER_ELEMENT;
|
|
1297
|
+
var EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES = 21;
|
|
1298
|
+
function extendedLightingSampledTextureCapacityAvailable(maxSampledTexturesPerShaderStage) {
|
|
1299
|
+
return maxSampledTexturesPerShaderStage !== void 0 && maxSampledTexturesPerShaderStage >= EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES;
|
|
1300
|
+
}
|
|
1301
|
+
function deriveExtendedLightingCapability(device) {
|
|
1302
|
+
const maxSampledTextures = device.limits.maxSampledTexturesPerShaderStage;
|
|
1303
|
+
if (!extendedLightingSampledTextureCapacityAvailable(maxSampledTextures)) {
|
|
1304
|
+
return {
|
|
1305
|
+
admitted: false,
|
|
1306
|
+
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
1307
|
+
reason: `maxSampledTexturesPerShaderStage ${maxSampledTextures ?? 0} < ${EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES}`
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
const maxLayers = device.limits.maxTextureArrayLayers ?? 0;
|
|
1311
|
+
const maxUniformBuffers = device.limits.maxUniformBuffersPerShaderStage ?? 0;
|
|
1312
|
+
if (maxLayers < IES_SLICE_CAPACITY) {
|
|
1313
|
+
return {
|
|
1314
|
+
admitted: false,
|
|
1315
|
+
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
1316
|
+
reason: `maxTextureArrayLayers ${maxLayers} < ${IES_SLICE_CAPACITY}`
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
if (maxUniformBuffers < 1) {
|
|
1320
|
+
return {
|
|
1321
|
+
admitted: false,
|
|
1322
|
+
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
1323
|
+
reason: `maxUniformBuffersPerShaderStage ${maxUniformBuffers} < 1`
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1326
|
+
if (!device.caps.storageBuffer || !device.caps.rgba16floatRenderable || !device.caps.samplerAliasing) {
|
|
1327
|
+
return {
|
|
1328
|
+
admitted: false,
|
|
1329
|
+
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
1330
|
+
reason: "required storage-buffer, rgba16float, or sampler capability is unavailable"
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
return { admitted: true, topology: EXTENDED_LIGHTING_TOPOLOGY, reason: void 0 };
|
|
1334
|
+
}
|
|
1335
|
+
var SHADOW_ATLAS_DEFAULT_FACE_SIZE = 512;
|
|
1336
|
+
var SHADOW_ATLAS_DEFAULT_LAYERS = 4;
|
|
1337
|
+
var ShadowAtlas = class {
|
|
1338
|
+
/** Backing cube_array depth texture. `null` until `ensure()` has run. */
|
|
1339
|
+
texture = null;
|
|
1340
|
+
/**
|
|
1341
|
+
* Whole-atlas cube_array sampling view used by URP shaders that bind the
|
|
1342
|
+
* atlas at `@group(0) @binding(5)`. `null` until `ensure()` has run.
|
|
1343
|
+
*/
|
|
1344
|
+
cubeArrayView = null;
|
|
1345
|
+
/** Comparison sampler for `texture_depth_cube_array`. */
|
|
1346
|
+
compareSampler = null;
|
|
1347
|
+
/** Per-face 2D depth view cache, keyed by `layer * 6 + face`. */
|
|
1348
|
+
faceViews = /* @__PURE__ */ new Map();
|
|
1349
|
+
/** Per-face label cache (debug aid). Reused on re-creation. */
|
|
1350
|
+
device;
|
|
1351
|
+
/** Per-face square size in pixels. */
|
|
1352
|
+
faceSize;
|
|
1353
|
+
/** Cube layer count. */
|
|
1354
|
+
layers;
|
|
1355
|
+
constructor(device, options = {}) {
|
|
1356
|
+
this.device = device;
|
|
1357
|
+
this.faceSize = options.faceSize ?? SHADOW_ATLAS_DEFAULT_FACE_SIZE;
|
|
1358
|
+
this.layers = options.layers ?? SHADOW_ATLAS_DEFAULT_LAYERS;
|
|
1359
|
+
}
|
|
1360
|
+
/**
|
|
1361
|
+
* Returns `true` once the atlas texture is allocated. Used by the extract /
|
|
1362
|
+
* record path to gate "no PointLightShadow → no allocation" (AC-09) — the
|
|
1363
|
+
* caller calls {@link ensure} on a frame that has at least one snapshot;
|
|
1364
|
+
* before that, `isAllocated()` stays `false` and tests can assert no GPU
|
|
1365
|
+
* resources were created.
|
|
1366
|
+
*/
|
|
1367
|
+
isAllocated() {
|
|
1368
|
+
return this.texture !== null;
|
|
1369
|
+
}
|
|
1370
|
+
/**
|
|
1371
|
+
* Lazy-allocate the atlas texture + cube_array sampling view + comparison
|
|
1372
|
+
* sampler. Idempotent: subsequent calls are zero-cost no-ops once the
|
|
1373
|
+
* resources exist.
|
|
1374
|
+
*
|
|
1375
|
+
* Throws (via the RHI error registry) on allocation failure. This is the
|
|
1376
|
+
* only path that touches the GPU — keeping it inside one method makes the
|
|
1377
|
+
* "zero-shadow scene = zero allocation" gate easy to enforce: the renderer
|
|
1378
|
+
* never calls this method on a frame with no PointLightShadow entities.
|
|
1379
|
+
*/
|
|
1380
|
+
ensure() {
|
|
1381
|
+
if (this.texture !== null) return;
|
|
1382
|
+
const usage = GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING;
|
|
1383
|
+
const texDesc = cubeArrayDepthDescriptor(this.faceSize, this.layers, usage);
|
|
1384
|
+
const texRes = this.device.createTexture(texDesc);
|
|
1385
|
+
if (!texRes.ok) throw texRes.error;
|
|
1386
|
+
this.texture = texRes.value;
|
|
1387
|
+
const viewRes = this.device.createTextureView(this.texture, {
|
|
1388
|
+
label: "shadow-atlas-cube-array-view",
|
|
1389
|
+
dimension: "cube-array",
|
|
1390
|
+
aspect: "depth-only",
|
|
1391
|
+
baseArrayLayer: 0,
|
|
1392
|
+
arrayLayerCount: 6 * this.layers,
|
|
1393
|
+
baseMipLevel: 0,
|
|
1394
|
+
mipLevelCount: 1
|
|
1395
|
+
});
|
|
1396
|
+
if (!viewRes.ok) {
|
|
1397
|
+
this.device.destroyTexture(this.texture);
|
|
1398
|
+
this.texture = null;
|
|
1399
|
+
throw viewRes.error;
|
|
1400
|
+
}
|
|
1401
|
+
this.cubeArrayView = viewRes.value;
|
|
1402
|
+
const sampRes = this.device.createSampler(comparisonSamplerDescriptor());
|
|
1403
|
+
if (!sampRes.ok) {
|
|
1404
|
+
this.device.destroyTexture(this.texture);
|
|
1405
|
+
this.texture = null;
|
|
1406
|
+
this.cubeArrayView = null;
|
|
1407
|
+
throw sampRes.error;
|
|
1408
|
+
}
|
|
1409
|
+
this.compareSampler = sampRes.value;
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* Whole-atlas cube_array sampling view (`texture_depth_cube_array`). Returns
|
|
1413
|
+
* `null` if the atlas is not yet allocated; the caller should gate on a
|
|
1414
|
+
* non-null pointShadow array before calling {@link ensure} + this getter.
|
|
1415
|
+
*/
|
|
1416
|
+
getAtlasView() {
|
|
1417
|
+
return this.cubeArrayView;
|
|
1418
|
+
}
|
|
1419
|
+
/**
|
|
1420
|
+
* Comparison sampler (`compare: 'less'`) for cube_array depth sampling.
|
|
1421
|
+
* Returns `null` if the atlas is not yet allocated.
|
|
1422
|
+
*/
|
|
1423
|
+
getComparisonSampler() {
|
|
1424
|
+
return this.compareSampler;
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Backing texture handle. Returns `null` if the atlas is not yet allocated.
|
|
1428
|
+
*/
|
|
1429
|
+
getTexture() {
|
|
1430
|
+
return this.texture;
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Lazy 2D depth view selecting `(layer, face)` (the caller passes
|
|
1434
|
+
* `shadowAtlasLayer` from the snapshot and a face index 0..5). Used as the
|
|
1435
|
+
* depth attachment of the shadow-caster render pass for one cube face.
|
|
1436
|
+
*
|
|
1437
|
+
* Caches per `(layer, face)` so the per-frame shadow loop pays zero
|
|
1438
|
+
* `createTextureView` cost after the first allocation. Cache is cleared on
|
|
1439
|
+
* {@link dispose}.
|
|
1440
|
+
*
|
|
1441
|
+
* @throws PointShadowAtlasUninitializedError if the atlas is not yet
|
|
1442
|
+
* allocated (caller must call {@link ensure} first).
|
|
1443
|
+
* @throws PointShadowAtlasBoundsViolationError if `layer` or `face` is out
|
|
1444
|
+
* of range.
|
|
1445
|
+
* @throws RhiError if the underlying `createTextureView` fails.
|
|
1446
|
+
*/
|
|
1447
|
+
faceView(layer, face) {
|
|
1448
|
+
if (this.texture === null) {
|
|
1449
|
+
throw new PointShadowAtlasUninitializedError();
|
|
1450
|
+
}
|
|
1451
|
+
if (layer < 0 || layer >= this.layers) {
|
|
1452
|
+
throw new PointShadowAtlasBoundsViolationError("layer", layer, this.layers);
|
|
1453
|
+
}
|
|
1454
|
+
if (face < 0 || face >= 6) {
|
|
1455
|
+
throw new PointShadowAtlasBoundsViolationError("face", face, 6);
|
|
1456
|
+
}
|
|
1457
|
+
const key = layer * 6 + face;
|
|
1458
|
+
const cached = this.faceViews.get(key);
|
|
1459
|
+
if (cached !== void 0) return cached;
|
|
1460
|
+
const desc = cubeArrayDepthFaceView(layer, face);
|
|
1461
|
+
const r = this.device.createTextureView(this.texture, desc);
|
|
1462
|
+
if (!r.ok) throw r.error;
|
|
1463
|
+
this.faceViews.set(key, r.value);
|
|
1464
|
+
return r.value;
|
|
1465
|
+
}
|
|
1466
|
+
/**
|
|
1467
|
+
* Release the GPU resources and clear the per-face view cache. Idempotent;
|
|
1468
|
+
* subsequent calls are zero-cost. After dispose, `isAllocated()` returns
|
|
1469
|
+
* `false` and the next `ensure()` re-allocates from scratch.
|
|
1470
|
+
*/
|
|
1471
|
+
dispose() {
|
|
1472
|
+
this.faceViews.clear();
|
|
1473
|
+
if (this.texture !== null) {
|
|
1474
|
+
this.device.destroyTexture(this.texture);
|
|
1475
|
+
this.texture = null;
|
|
1476
|
+
}
|
|
1477
|
+
this.cubeArrayView = null;
|
|
1478
|
+
this.compareSampler = null;
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
function worldEntityKey(worldId, entityKey) {
|
|
1482
|
+
return worldId * 4294967296 + entityKey;
|
|
1483
|
+
}
|
|
1484
|
+
function instanceCollectionCacheKey(worldId, instance) {
|
|
1485
|
+
return -(4294967296 + worldEntityKey(worldId, instance.collectionId ?? instance.cacheKey));
|
|
1486
|
+
}
|
|
1487
|
+
var ZERO_CAMERA_CLEAR_FALLBACK = [0, 0, 0, 1];
|
|
1488
|
+
var textureIdentities = /* @__PURE__ */ new WeakMap();
|
|
1489
|
+
var nextTextureIdentity = 1;
|
|
1490
|
+
var opaqueResourceIdentities = /* @__PURE__ */ new WeakMap();
|
|
1491
|
+
var nextOpaqueResourceIdentity = 1;
|
|
1492
|
+
function getOpaqueResourceIdentity(resource) {
|
|
1493
|
+
const existing = opaqueResourceIdentities.get(resource);
|
|
1494
|
+
if (existing !== void 0) return existing;
|
|
1495
|
+
const identity = nextOpaqueResourceIdentity++;
|
|
1496
|
+
opaqueResourceIdentities.set(resource, identity);
|
|
1497
|
+
return identity;
|
|
1498
|
+
}
|
|
1499
|
+
function getTextureIdentity(texture) {
|
|
1500
|
+
const object = texture;
|
|
1501
|
+
const existing = textureIdentities.get(object);
|
|
1502
|
+
if (existing !== void 0) return existing;
|
|
1503
|
+
const identity = nextTextureIdentity++;
|
|
1504
|
+
textureIdentities.set(object, identity);
|
|
1505
|
+
return identity;
|
|
1506
|
+
}
|
|
1507
|
+
function validateGraphTargetCaptureReadback(input) {
|
|
1508
|
+
const { bytes, expectedByteLength, sentinel, allowZero = false } = input;
|
|
1509
|
+
if (bytes.byteLength !== expectedByteLength)
|
|
1510
|
+
return { ok: false, code: "capture-readback-length" };
|
|
1511
|
+
if (sentinel?.every((value, index2) => bytes[index2] === value)) {
|
|
1512
|
+
return { ok: false, code: "capture-readback-untouched-sentinel" };
|
|
1513
|
+
}
|
|
1514
|
+
if (!allowZero && bytes.every((value) => value === 0)) {
|
|
1515
|
+
return { ok: false, code: "capture-readback-empty" };
|
|
1516
|
+
}
|
|
1517
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1518
|
+
let index = 0;
|
|
1519
|
+
for (; index + 3 < bytes.byteLength; index += 4) {
|
|
1520
|
+
const word = view.getUint32(index, true);
|
|
1521
|
+
if ((word & 31744) === 31744 || (word & 2080374784) === 2080374784)
|
|
1522
|
+
return { ok: false, code: "capture-readback-non-finite" };
|
|
1523
|
+
}
|
|
1524
|
+
if (index + 1 < bytes.byteLength && (view.getUint16(index, true) & 31744) === 31744)
|
|
1525
|
+
return { ok: false, code: "capture-readback-non-finite" };
|
|
1526
|
+
return { ok: true };
|
|
1527
|
+
}
|
|
1528
|
+
function makeZeroCameraFallbackSnapshot() {
|
|
1529
|
+
const identityWorld = new Float32Array(16);
|
|
1530
|
+
identityWorld[0] = 1;
|
|
1531
|
+
identityWorld[5] = 1;
|
|
1532
|
+
identityWorld[10] = 1;
|
|
1533
|
+
identityWorld[15] = 1;
|
|
1534
|
+
return {
|
|
1535
|
+
position: vec3.create(0, 0, 0),
|
|
1536
|
+
world: identityWorld,
|
|
1537
|
+
fov: Math.PI / 4,
|
|
1538
|
+
aspect: 1,
|
|
1539
|
+
near: 0.1,
|
|
1540
|
+
far: 100,
|
|
1541
|
+
// feat-20260613 M6 / w20: synthetic camera defaults to perspective so
|
|
1542
|
+
// the CSM extract path stays consistent with the previously-implicit
|
|
1543
|
+
// perspective shape (unchanged behavior; explicit field).
|
|
1544
|
+
projection: "perspective",
|
|
1545
|
+
orthoLeft: -1,
|
|
1546
|
+
orthoRight: 1,
|
|
1547
|
+
orthoBottom: -1,
|
|
1548
|
+
orthoTop: 1,
|
|
1549
|
+
tonemap: "none",
|
|
1550
|
+
exposure: 1,
|
|
1551
|
+
whitePoint: 4,
|
|
1552
|
+
antialias: "none",
|
|
1553
|
+
bloom: "off",
|
|
1554
|
+
bloomThreshold: 1,
|
|
1555
|
+
bloomIntensity: 1,
|
|
1556
|
+
bloomSoftKnee: 0.5,
|
|
1557
|
+
bloomScatter: 0.7,
|
|
1558
|
+
clearColor: ZERO_CAMERA_CLEAR_FALLBACK
|
|
1559
|
+
};
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// src/errors/gpu-driven.ts
|
|
1563
|
+
var ERROR_POLICY2 = {
|
|
1564
|
+
"missing-material-receipt": {
|
|
1565
|
+
expected: "a producer-owned material program receipt is present",
|
|
1566
|
+
hint: "cook and load the selected material program artifact, then retry preparation",
|
|
1567
|
+
recovery: "rebuild-producer"
|
|
1568
|
+
},
|
|
1569
|
+
"material-abi-not-executable": {
|
|
1570
|
+
expected: "the published material ABI fits the GPU Scene submission layout",
|
|
1571
|
+
hint: "recook the material with a scene-index ABI supported by the GPU-driven owner or keep it on its authored lane",
|
|
1572
|
+
recovery: "route-cpu-lane"
|
|
1573
|
+
},
|
|
1574
|
+
"missing-uv": {
|
|
1575
|
+
expected: "the geometry exposes every UV set named by the material receipt",
|
|
1576
|
+
hint: "repair the geometry UV semantic or route the draw to the CPU semantic lane",
|
|
1577
|
+
recovery: "route-cpu-lane"
|
|
1578
|
+
},
|
|
1579
|
+
"reflection-mismatch": {
|
|
1580
|
+
expected: "the loaded reflection receipt matches the artifact layout identity",
|
|
1581
|
+
hint: "rebuild the material artifact and reflection from one source, then retry",
|
|
1582
|
+
recovery: "rebuild-producer"
|
|
1583
|
+
},
|
|
1584
|
+
"vertex-input-mismatch": {
|
|
1585
|
+
expected: "geometry vertex semantics match the material reflection receipt",
|
|
1586
|
+
hint: "repair the geometry vertex semantic layout or route the draw to the CPU lane",
|
|
1587
|
+
recovery: "route-cpu-lane"
|
|
1588
|
+
},
|
|
1589
|
+
"alpha-mask-mismatch": {
|
|
1590
|
+
expected: "the Alpha Mask cutoff is present in the material receipt",
|
|
1591
|
+
hint: "declare the pass coverage cutoff in the material schema and recook it",
|
|
1592
|
+
recovery: "rebuild-producer"
|
|
1593
|
+
},
|
|
1594
|
+
"resource-not-ready": {
|
|
1595
|
+
expected: "all material resource slots have resolved handles",
|
|
1596
|
+
hint: "resolve the declared texture and sampler resources before recording",
|
|
1597
|
+
recovery: "retry-same-draw"
|
|
1598
|
+
},
|
|
1599
|
+
"stale-generation": {
|
|
1600
|
+
expected: "receipt and prepared inputs belong to the requested generation",
|
|
1601
|
+
hint: "discard stale GPU facts, rebuild the producer receipt, and retry the same draw",
|
|
1602
|
+
recovery: "rebuild-generation"
|
|
1603
|
+
},
|
|
1604
|
+
"skin-receipt-mismatch": {
|
|
1605
|
+
expected: "skinned geometry has a current palette address receipt",
|
|
1606
|
+
hint: "rebuild the Skin palette receipt for this generation before recording",
|
|
1607
|
+
recovery: "rebuild-producer"
|
|
1608
|
+
},
|
|
1609
|
+
"shadow-ownership": {
|
|
1610
|
+
expected: "every declared ShadowCaster pass has one GPU-compatible draw-item owner",
|
|
1611
|
+
hint: "repair the ShadowCaster producer membership or keep the residual on its explicit CPU lane",
|
|
1612
|
+
recovery: "route-cpu-lane"
|
|
1613
|
+
}
|
|
1614
|
+
};
|
|
1615
|
+
var GpuDrivenPreparationError = class extends Error {
|
|
1616
|
+
code;
|
|
1617
|
+
expected;
|
|
1618
|
+
hint;
|
|
1619
|
+
detail;
|
|
1620
|
+
constructor(code, detail) {
|
|
1621
|
+
const policy = ERROR_POLICY2[code];
|
|
1622
|
+
super(`[GpuDrivenPreparationError ${code}] ${policy.expected}`);
|
|
1623
|
+
this.name = "GpuDrivenPreparationError";
|
|
1624
|
+
this.code = code;
|
|
1625
|
+
this.expected = policy.expected;
|
|
1626
|
+
this.hint = policy.hint;
|
|
1627
|
+
this.detail = Object.freeze({
|
|
1628
|
+
...detail,
|
|
1629
|
+
recovery: detail.recovery ?? policy.recovery
|
|
1630
|
+
});
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
var MATRIX_STRIDE = 16;
|
|
1634
|
+
var InstanceTransformsError = class extends Error {
|
|
1635
|
+
constructor(detail) {
|
|
1636
|
+
super("Instances.transforms must contain complete finite matrices");
|
|
1637
|
+
this.detail = detail;
|
|
1638
|
+
this.name = "InstanceTransformsError";
|
|
1639
|
+
}
|
|
1640
|
+
detail;
|
|
1641
|
+
code = "instance-transforms-invalid";
|
|
1642
|
+
expected = "finite column-major mat4 values, with transforms.length a multiple of 16";
|
|
1643
|
+
hint = "repair Instances.transforms in the World or source SceneAsset and retry";
|
|
1644
|
+
};
|
|
1645
|
+
function validateInstanceTransforms(transforms) {
|
|
1646
|
+
if (transforms.length % MATRIX_STRIDE !== 0)
|
|
1647
|
+
return new InstanceTransformsStrideMismatchError(transforms.length);
|
|
1648
|
+
for (let index = 0; index < transforms.length; index++) {
|
|
1649
|
+
if (!Number.isFinite(transforms[index]))
|
|
1650
|
+
return new InstanceTransformsError({
|
|
1651
|
+
actualLength: transforms.length,
|
|
1652
|
+
nonFiniteIndex: index
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
return void 0;
|
|
1656
|
+
}
|
|
1657
|
+
function instanceUploadRangesForResident(activeIsNew, dirtyRanges, fullRange) {
|
|
1658
|
+
return activeIsNew ? [fullRange] : dirtyRanges;
|
|
1659
|
+
}
|
|
1660
|
+
var InstanceProjectionStore = class {
|
|
1661
|
+
nextId = 1;
|
|
1662
|
+
nextGeneration = 1;
|
|
1663
|
+
identities = /* @__PURE__ */ new WeakMap();
|
|
1664
|
+
records = /* @__PURE__ */ new Map();
|
|
1665
|
+
residency = /* @__PURE__ */ new Map();
|
|
1666
|
+
project(world, entity, transforms) {
|
|
1667
|
+
const collectionId = this.identities.get(world)?.get(entity) ?? this.nextId++;
|
|
1668
|
+
const previous = this.records.get(collectionId);
|
|
1669
|
+
if (previous !== void 0 && previous.transforms.length === transforms.length && previous.transforms.every((value, index) => Object.is(value, transforms[index])))
|
|
1670
|
+
return previous;
|
|
1671
|
+
const count = transforms.length / MATRIX_STRIDE;
|
|
1672
|
+
const generations = previous?.count === count ? previous.generations : Uint32Array.from({ length: count }, () => this.nextGeneration++);
|
|
1673
|
+
const record = {
|
|
1674
|
+
collectionId,
|
|
1675
|
+
world,
|
|
1676
|
+
entity,
|
|
1677
|
+
transforms: new Float32Array(transforms),
|
|
1678
|
+
generations,
|
|
1679
|
+
count,
|
|
1680
|
+
revision: (previous?.revision ?? 0) + 1
|
|
1681
|
+
};
|
|
1682
|
+
return record;
|
|
1683
|
+
}
|
|
1684
|
+
/** Called only after the owning RenderScene accepts its prepared changes. */
|
|
1685
|
+
accept(world, entity, snapshot) {
|
|
1686
|
+
const { collectionId, revision, transforms, generations } = snapshot;
|
|
1687
|
+
if (collectionId === void 0 || revision === void 0 || generations === void 0) return;
|
|
1688
|
+
let entities = this.identities.get(world);
|
|
1689
|
+
if (entities === void 0) {
|
|
1690
|
+
entities = /* @__PURE__ */ new Map();
|
|
1691
|
+
this.identities.set(world, entities);
|
|
1692
|
+
}
|
|
1693
|
+
entities.set(entity, collectionId);
|
|
1694
|
+
this.records.set(collectionId, {
|
|
1695
|
+
collectionId,
|
|
1696
|
+
revision,
|
|
1697
|
+
transforms,
|
|
1698
|
+
generations,
|
|
1699
|
+
count: transforms.length / MATRIX_STRIDE,
|
|
1700
|
+
world,
|
|
1701
|
+
entity
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
release(world, entity) {
|
|
1705
|
+
const entities = this.identities.get(world);
|
|
1706
|
+
const id = entities?.get(entity);
|
|
1707
|
+
if (id === void 0) return;
|
|
1708
|
+
entities?.delete(entity);
|
|
1709
|
+
this.records.delete(id);
|
|
1710
|
+
this.residency.delete(id);
|
|
1711
|
+
}
|
|
1712
|
+
retain(ids) {
|
|
1713
|
+
for (const record of this.records.values()) {
|
|
1714
|
+
if (!ids.has(record.collectionId)) this.release(record.world, record.entity);
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
dispose() {
|
|
1718
|
+
this.records.clear();
|
|
1719
|
+
this.residency.clear();
|
|
1720
|
+
this.identities = /* @__PURE__ */ new WeakMap();
|
|
1721
|
+
}
|
|
1722
|
+
_resetResidency() {
|
|
1723
|
+
this.residency.clear();
|
|
1724
|
+
}
|
|
1725
|
+
_reportResidency(input) {
|
|
1726
|
+
if (!this.records.has(input.collectionId)) return;
|
|
1727
|
+
const previous = this.residency.get(input.collectionId);
|
|
1728
|
+
const sameFrame = previous?.frameNumber === input.frameNumber && previous.error === void 0;
|
|
1729
|
+
const ranges = [...sameFrame ? previous.uploadRanges : [], ...input.uploadRanges].map((range) => ({ ...range })).sort((a, b) => a.start - b.start);
|
|
1730
|
+
const uploadRanges = [];
|
|
1731
|
+
for (const range of ranges) {
|
|
1732
|
+
const last = uploadRanges.at(-1);
|
|
1733
|
+
if (last !== void 0 && range.start <= last.end) last.end = Math.max(last.end, range.end);
|
|
1734
|
+
else uploadRanges.push(range);
|
|
1735
|
+
}
|
|
1736
|
+
this.residency.set(input.collectionId, {
|
|
1737
|
+
...input,
|
|
1738
|
+
uploadRanges,
|
|
1739
|
+
uploadedBytes: input.uploadedBytes + (sameFrame ? previous.uploadedBytes : 0),
|
|
1740
|
+
error: void 0
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1743
|
+
_reportFailure(input) {
|
|
1744
|
+
if (!this.records.has(input.collectionId)) return;
|
|
1745
|
+
this.residency.set(input.collectionId, {
|
|
1746
|
+
frameNumber: -1,
|
|
1747
|
+
residentGeneration: void 0,
|
|
1748
|
+
lane: "unavailable",
|
|
1749
|
+
uploadRanges: [],
|
|
1750
|
+
uploadedBytes: 0,
|
|
1751
|
+
requestedBytes: input.facts.requestedBytes,
|
|
1752
|
+
supportedBytes: input.facts.supportedBytes,
|
|
1753
|
+
backend: input.facts.backend,
|
|
1754
|
+
error: {
|
|
1755
|
+
code: input.code,
|
|
1756
|
+
expected: input.expected,
|
|
1757
|
+
hint: input.hint,
|
|
1758
|
+
detail: { ...input.facts }
|
|
1759
|
+
}
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
_inspections(frameNumber) {
|
|
1763
|
+
return [...this.records.values()].map((record) => {
|
|
1764
|
+
const resident = this.residency.get(record.collectionId);
|
|
1765
|
+
const current = resident?.frameNumber === frameNumber;
|
|
1766
|
+
return {
|
|
1767
|
+
collectionId: record.collectionId,
|
|
1768
|
+
count: record.count,
|
|
1769
|
+
revision: record.revision,
|
|
1770
|
+
residentGeneration: resident?.residentGeneration,
|
|
1771
|
+
lane: resident?.lane ?? "unresident",
|
|
1772
|
+
uploadRanges: current ? resident.uploadRanges.map((range) => ({ ...range })) : [],
|
|
1773
|
+
uploadedBytes: current ? resident.uploadedBytes : 0,
|
|
1774
|
+
requestedBytes: resident?.requestedBytes ?? record.transforms.byteLength,
|
|
1775
|
+
supportedBytes: resident?.supportedBytes,
|
|
1776
|
+
backend: resident?.backend ?? "unknown",
|
|
1777
|
+
owner: "renderer.instances",
|
|
1778
|
+
error: resident?.error
|
|
1779
|
+
};
|
|
1780
|
+
});
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
|
|
1784
|
+
// src/scene/visibility/budget.ts
|
|
1785
|
+
var DEFAULT_CONFIGURED_QUERY_BUDGET = 2048;
|
|
1786
|
+
var MAX_QUERY_BUDGET = 4096;
|
|
1787
|
+
var VISIBILITY_CANDIDATE_COUNT = 1e5;
|
|
1788
|
+
var VISIBILITY_OCCLUDED_COUNT = 9e4;
|
|
1789
|
+
function createVisibilityBudget(configuredQueryBudget = DEFAULT_CONFIGURED_QUERY_BUDGET) {
|
|
1790
|
+
if (!Number.isSafeInteger(configuredQueryBudget) || configuredQueryBudget <= 0) {
|
|
1791
|
+
throw new RangeError("configuredQueryBudget must be a positive safe integer");
|
|
1792
|
+
}
|
|
1793
|
+
const effectiveQueryBudget = Math.min(configuredQueryBudget, MAX_QUERY_BUDGET);
|
|
1794
|
+
const oneSweepCandidates = oneSweep(VISIBILITY_CANDIDATE_COUNT, effectiveQueryBudget);
|
|
1795
|
+
const oneSweepOccluded = oneSweep(VISIBILITY_OCCLUDED_COUNT, effectiveQueryBudget);
|
|
1796
|
+
const retestSubmits = Math.max(6, oneSweepOccluded);
|
|
1797
|
+
return Object.freeze({
|
|
1798
|
+
configuredQueryBudget,
|
|
1799
|
+
effectiveQueryBudget,
|
|
1800
|
+
oneSweepCandidates,
|
|
1801
|
+
oneSweepOccluded,
|
|
1802
|
+
settleSubmits: 2 * oneSweepCandidates,
|
|
1803
|
+
retestSubmits,
|
|
1804
|
+
expirySubmits: Math.max(8, retestSubmits + oneSweepOccluded)
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
function oneSweep(candidateCount, effectiveQueryBudget) {
|
|
1808
|
+
return Math.ceil(candidateCount / effectiveQueryBudget);
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
// src/render-contract.ts
|
|
1812
|
+
var STANDARD_OUTPUT_TRANSFORM_FEATURE_ID = "forgeax::standard::output-transform";
|
|
1813
|
+
var FXAA_POST_PROCESS_ID = "forgeax::post::fxaa";
|
|
1814
|
+
var RENDER_GRAPH_EXECUTION_PHASE_CATALOG = [
|
|
1815
|
+
"record/graph-execute/point-shadow",
|
|
1816
|
+
"record/graph-execute/cluster-binner-upload",
|
|
1817
|
+
"record/graph-execute/g-buffer",
|
|
1818
|
+
"record/graph-execute/g-buffer/geometry-loop",
|
|
1819
|
+
"record/graph-execute/g-buffer/material-bind-groups",
|
|
1820
|
+
"record/graph-execute/g-buffer/pipeline-selection",
|
|
1821
|
+
"record/graph-execute/g-buffer/draw-submit",
|
|
1822
|
+
"record/graph-execute/ssao-calc",
|
|
1823
|
+
"record/graph-execute/ssao-blur",
|
|
1824
|
+
"record/graph-execute/lighting",
|
|
1825
|
+
"record/graph-execute/forward",
|
|
1826
|
+
"record/graph-execute/forward/geometry-loop",
|
|
1827
|
+
"record/graph-execute/forward/material-bind-groups",
|
|
1828
|
+
"record/graph-execute/forward/pipeline-selection",
|
|
1829
|
+
"record/graph-execute/forward/draw-submit",
|
|
1830
|
+
"record/graph-execute/output-transform",
|
|
1831
|
+
"record/graph-execute/present",
|
|
1832
|
+
"record/graph-execute/debug-overlay",
|
|
1833
|
+
"record/graph-execute/shadow",
|
|
1834
|
+
"record/graph-execute/spot-shadow",
|
|
1835
|
+
"record/graph-execute/skybox",
|
|
1836
|
+
"record/graph-execute/main",
|
|
1837
|
+
"record/graph-execute/fxaa",
|
|
1838
|
+
"record/graph-execute/bloom-downsample",
|
|
1839
|
+
"record/graph-execute/bloom-upsample",
|
|
1840
|
+
"record/graph-execute/bloom-composite",
|
|
1841
|
+
"record/graph-execute/ssr-hiz",
|
|
1842
|
+
"record/graph-execute/ssr-trace",
|
|
1843
|
+
"record/graph-execute/ssr-temporal",
|
|
1844
|
+
"record/graph-execute/ssr-reflection-mip",
|
|
1845
|
+
"record/graph-execute/ssr-compose",
|
|
1846
|
+
"record/graph-execute/other"
|
|
1847
|
+
];
|
|
1848
|
+
var RENDER_HDRP_BINNER_PHASE_CATALOG = [
|
|
1849
|
+
"record/scene-state/hdrp-cluster/binner/light-bounds-and-occupancy",
|
|
1850
|
+
"record/scene-state/hdrp-cluster/binner/light-bounds-and-occupancy/light-aabb",
|
|
1851
|
+
"record/scene-state/hdrp-cluster/binner/light-bounds-and-occupancy/cluster-occupancy",
|
|
1852
|
+
"record/scene-state/hdrp-cluster/binner/cluster-reserve",
|
|
1853
|
+
"record/scene-state/hdrp-cluster/binner/input-preparation",
|
|
1854
|
+
"record/scene-state/hdrp-cluster/binner/bin-core",
|
|
1855
|
+
"record/scene-state/hdrp-cluster/binner/light-index-write",
|
|
1856
|
+
"record/scene-state/hdrp-cluster/binner/light-index-write/bounds-read",
|
|
1857
|
+
"record/scene-state/hdrp-cluster/binner/light-index-write/cluster-write"
|
|
1858
|
+
];
|
|
1859
|
+
var RENDER_HDRP_CLUSTER_PHASE_CATALOG = [
|
|
1860
|
+
"record/scene-state/hdrp-cluster/binner",
|
|
1861
|
+
...RENDER_HDRP_BINNER_PHASE_CATALOG,
|
|
1862
|
+
"record/scene-state/hdrp-cluster/payload-packing",
|
|
1863
|
+
"record/scene-state/hdrp-cluster/buffer-upload"
|
|
1864
|
+
];
|
|
1865
|
+
var RENDER_SCENE_STATE_PHASE_CATALOG = [
|
|
1866
|
+
"record/scene-state/fold-buckets",
|
|
1867
|
+
"record/scene-state/lighting-prep",
|
|
1868
|
+
"record/scene-state/ambient-resolution",
|
|
1869
|
+
"record/scene-state/directional-shadow-cache",
|
|
1870
|
+
"record/scene-state/hdrp-cluster",
|
|
1871
|
+
...RENDER_HDRP_CLUSTER_PHASE_CATALOG
|
|
1872
|
+
];
|
|
1873
|
+
var RENDER_RECORD_PHASE_CATALOG = [
|
|
1874
|
+
"record/occlusion-query-submit",
|
|
1875
|
+
"record/occlusion-global-advance",
|
|
1876
|
+
"record/scene-state",
|
|
1877
|
+
...RENDER_SCENE_STATE_PHASE_CATALOG,
|
|
1878
|
+
"record/swapchain",
|
|
1879
|
+
"record/render-graph",
|
|
1880
|
+
"record/target-views",
|
|
1881
|
+
"record/validation",
|
|
1882
|
+
"record/dispatch-plan",
|
|
1883
|
+
"record/uploads",
|
|
1884
|
+
"record/bind-groups",
|
|
1885
|
+
"record/graph-execute",
|
|
1886
|
+
...RENDER_GRAPH_EXECUTION_PHASE_CATALOG
|
|
1887
|
+
];
|
|
1888
|
+
var RENDER_PHASE_CATALOG = [
|
|
1889
|
+
"extract",
|
|
1890
|
+
"occlusion-prepare",
|
|
1891
|
+
"bind-groups",
|
|
1892
|
+
"features",
|
|
1893
|
+
"sort",
|
|
1894
|
+
"record",
|
|
1895
|
+
...RENDER_RECORD_PHASE_CATALOG
|
|
1896
|
+
];
|
|
1897
|
+
|
|
1898
|
+
// src/targets/material-source.ts
|
|
1899
|
+
var sourceBindings = /* @__PURE__ */ new WeakMap();
|
|
1900
|
+
var targetIdentities = /* @__PURE__ */ new WeakMap();
|
|
1901
|
+
var nextTargetIdentity = 1;
|
|
1902
|
+
function targetIdentity(target) {
|
|
1903
|
+
const object = target;
|
|
1904
|
+
const existing = targetIdentities.get(object);
|
|
1905
|
+
if (existing !== void 0) return existing;
|
|
1906
|
+
const identity = nextTargetIdentity;
|
|
1907
|
+
nextTargetIdentity += 1;
|
|
1908
|
+
targetIdentities.set(object, identity);
|
|
1909
|
+
return identity;
|
|
1910
|
+
}
|
|
1911
|
+
function sourceToken() {
|
|
1912
|
+
return Object.freeze({});
|
|
1913
|
+
}
|
|
1914
|
+
function resolveRenderTargetMaterialSource(source) {
|
|
1915
|
+
return sourceBindings.get(source);
|
|
1916
|
+
}
|
|
1917
|
+
function renderTargetMaterialSourceIdentity(source) {
|
|
1918
|
+
const binding = resolveRenderTargetMaterialSource(source);
|
|
1919
|
+
if (binding === void 0) return void 0;
|
|
1920
|
+
return [
|
|
1921
|
+
targetIdentity(binding.target),
|
|
1922
|
+
binding.generation,
|
|
1923
|
+
binding.shape,
|
|
1924
|
+
binding.format,
|
|
1925
|
+
binding.view.dimension,
|
|
1926
|
+
binding.view.mipLevel,
|
|
1927
|
+
binding.view.resolveRequired ? 1 : 0
|
|
1928
|
+
].join(":");
|
|
1929
|
+
}
|
|
1930
|
+
function invalid(field, value, expected) {
|
|
1931
|
+
return {
|
|
1932
|
+
ok: false,
|
|
1933
|
+
error: new RenderTargetDescriptorInvalidError({ field, value, expected })
|
|
1934
|
+
};
|
|
1935
|
+
}
|
|
1936
|
+
function createRenderTargetMaterialSource(target, descriptor, options) {
|
|
1937
|
+
if (options.aspect !== "color") return invalid("aspect", options.aspect, "color");
|
|
1938
|
+
if (options.dimension !== descriptor.shape) {
|
|
1939
|
+
return invalid("dimension", options.dimension, `dimension matches ${descriptor.shape}`);
|
|
1940
|
+
}
|
|
1941
|
+
const mipCount = descriptor.mipLevels === 1 ? 1 : Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;
|
|
1942
|
+
if (!Number.isInteger(options.mipLevel) || options.mipLevel < 0 || options.mipLevel >= mipCount) {
|
|
1943
|
+
return invalid("mipLevel", options.mipLevel, `an admitted mip level below ${mipCount}`);
|
|
1944
|
+
}
|
|
1945
|
+
if (!Number.isInteger(options.generation) || options.generation < 0) {
|
|
1946
|
+
return invalid("generation", options.generation, "a non-negative device generation");
|
|
1947
|
+
}
|
|
1948
|
+
const result = {
|
|
1949
|
+
ok: true,
|
|
1950
|
+
value: Object.freeze({
|
|
1951
|
+
source: sourceToken(),
|
|
1952
|
+
target,
|
|
1953
|
+
generation: options.generation,
|
|
1954
|
+
shape: descriptor.shape,
|
|
1955
|
+
format: descriptor.format,
|
|
1956
|
+
view: Object.freeze({
|
|
1957
|
+
dimension: options.dimension,
|
|
1958
|
+
mipLevel: options.mipLevel,
|
|
1959
|
+
resolveRequired: descriptor.sampleCount === 4
|
|
1960
|
+
})
|
|
1961
|
+
})
|
|
1962
|
+
};
|
|
1963
|
+
sourceBindings.set(result.value.source, result.value);
|
|
1964
|
+
return result;
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
// src/gpu-stage.ts
|
|
1968
|
+
var GPU_SHADER_STAGE_VERTEX = 1;
|
|
1969
|
+
var GPU_SHADER_STAGE_FRAGMENT = 2;
|
|
1970
|
+
var GPU_SHADER_STAGE_COMPUTE = 4;
|
|
1971
|
+
var BGL_ONLY_SPEC_STUB = Object.freeze({
|
|
1972
|
+
shader: { id: "", passKind: "forward", variantSet: void 0 },
|
|
1973
|
+
attachments: { colorFormats: [], depthFormat: void 0, sampleCount: 1 },
|
|
1974
|
+
geometry: { topology: "triangle-list", vertexLayout: {} },
|
|
1975
|
+
renderState: void 0
|
|
1976
|
+
});
|
|
1977
|
+
function buildPbrMaterialUserRegionEntries(paramSchema = STANDARD_PIPELINE_PARAM_SCHEMA, excludedTextureFields = []) {
|
|
1978
|
+
const excluded = new Set(excludedTextureFields);
|
|
1979
|
+
for (const field of standardPhysicalTextureFields(paramSchema)) excluded.add(field);
|
|
1980
|
+
const derived = derive(
|
|
1981
|
+
excluded.size === 0 ? paramSchema : paramSchema.filter(
|
|
1982
|
+
(entry) => !excluded.has(entry.name) || !entry.type.startsWith("texture")
|
|
1983
|
+
)
|
|
1984
|
+
);
|
|
1985
|
+
let entries = derived.bglEntries.map(
|
|
1986
|
+
(entry) => ({
|
|
1987
|
+
binding: entry.binding,
|
|
1988
|
+
visibility: entry.visibility,
|
|
1989
|
+
...entry.buffer === void 0 ? {} : { buffer: entry.buffer },
|
|
1990
|
+
...entry.sampler === void 0 ? {} : { sampler: entry.sampler },
|
|
1991
|
+
...entry.texture === void 0 ? {} : { texture: entry.texture },
|
|
1992
|
+
...entry.storageTexture === void 0 ? {} : { storageTexture: entry.storageTexture }
|
|
1993
|
+
})
|
|
1994
|
+
);
|
|
1995
|
+
const ubo = entries[0];
|
|
1996
|
+
if (ubo !== void 0 && ubo.binding === 0 && ubo.buffer?.type === "uniform") {
|
|
1997
|
+
entries[0] = {
|
|
1998
|
+
binding: 0,
|
|
1999
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2000
|
+
buffer: { type: "uniform", hasDynamicOffset: true }
|
|
2001
|
+
};
|
|
2002
|
+
} else {
|
|
2003
|
+
entries = [
|
|
2004
|
+
{
|
|
2005
|
+
binding: 0,
|
|
2006
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2007
|
+
buffer: { type: "uniform", hasDynamicOffset: true }
|
|
2008
|
+
},
|
|
2009
|
+
...entries.map((entry) => ({ ...entry, binding: entry.binding + 1 }))
|
|
2010
|
+
];
|
|
2011
|
+
}
|
|
2012
|
+
return entries;
|
|
2013
|
+
}
|
|
2014
|
+
function appendInjection(bgl, kind) {
|
|
2015
|
+
const start = bgl.length;
|
|
2016
|
+
switch (kind) {
|
|
2017
|
+
case "ibl":
|
|
2018
|
+
return [
|
|
2019
|
+
// binding start+0: irradianceMap (texture_cube)
|
|
2020
|
+
{
|
|
2021
|
+
binding: start,
|
|
2022
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2023
|
+
texture: { sampleType: "float", viewDimension: "cube" }
|
|
2024
|
+
},
|
|
2025
|
+
// binding start+1: irradianceSampler
|
|
2026
|
+
{
|
|
2027
|
+
binding: start + 1,
|
|
2028
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2029
|
+
sampler: { type: "filtering" }
|
|
2030
|
+
},
|
|
2031
|
+
// binding start+2: prefilterMap (texture_cube)
|
|
2032
|
+
{
|
|
2033
|
+
binding: start + 2,
|
|
2034
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2035
|
+
texture: { sampleType: "float", viewDimension: "cube" }
|
|
2036
|
+
},
|
|
2037
|
+
// binding start+3: prefilterSampler
|
|
2038
|
+
{
|
|
2039
|
+
binding: start + 3,
|
|
2040
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2041
|
+
sampler: { type: "filtering" }
|
|
2042
|
+
},
|
|
2043
|
+
// binding start+4: brdfLut (texture_2d)
|
|
2044
|
+
{
|
|
2045
|
+
binding: start + 4,
|
|
2046
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2047
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2048
|
+
},
|
|
2049
|
+
// binding start+5: uniform { intensity: f32 }
|
|
2050
|
+
{
|
|
2051
|
+
binding: start + 5,
|
|
2052
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2053
|
+
buffer: { type: "uniform" }
|
|
2054
|
+
}
|
|
2055
|
+
];
|
|
2056
|
+
case "lightmap":
|
|
2057
|
+
return [
|
|
2058
|
+
// emissive sampler + texture pair
|
|
2059
|
+
{
|
|
2060
|
+
binding: start,
|
|
2061
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2062
|
+
sampler: { type: "filtering" }
|
|
2063
|
+
},
|
|
2064
|
+
{
|
|
2065
|
+
binding: start + 1,
|
|
2066
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2067
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2068
|
+
},
|
|
2069
|
+
// occlusion sampler + texture pair
|
|
2070
|
+
{
|
|
2071
|
+
binding: start + 2,
|
|
2072
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2073
|
+
sampler: { type: "filtering" }
|
|
2074
|
+
},
|
|
2075
|
+
{
|
|
2076
|
+
binding: start + 3,
|
|
2077
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2078
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2079
|
+
}
|
|
2080
|
+
];
|
|
2081
|
+
case "shadow":
|
|
2082
|
+
return [
|
|
2083
|
+
{
|
|
2084
|
+
binding: start,
|
|
2085
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2086
|
+
sampler: { type: "comparison" }
|
|
2087
|
+
},
|
|
2088
|
+
{
|
|
2089
|
+
binding: start + 1,
|
|
2090
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2091
|
+
texture: { sampleType: "depth", viewDimension: "2d" }
|
|
2092
|
+
}
|
|
2093
|
+
];
|
|
2094
|
+
case "transmission":
|
|
2095
|
+
return [
|
|
2096
|
+
{
|
|
2097
|
+
binding: start,
|
|
2098
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2099
|
+
sampler: { type: "filtering" }
|
|
2100
|
+
},
|
|
2101
|
+
{
|
|
2102
|
+
binding: start + 1,
|
|
2103
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2104
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2105
|
+
}
|
|
2106
|
+
];
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
function appendSingleLayerMediumInjection(bgl) {
|
|
2110
|
+
const start = bgl.length;
|
|
2111
|
+
return [
|
|
2112
|
+
{
|
|
2113
|
+
binding: start,
|
|
2114
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2115
|
+
sampler: { type: "non-filtering" }
|
|
2116
|
+
},
|
|
2117
|
+
{
|
|
2118
|
+
binding: start + 1,
|
|
2119
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2120
|
+
texture: { sampleType: "unfilterable-float", viewDimension: "2d" }
|
|
2121
|
+
},
|
|
2122
|
+
{
|
|
2123
|
+
binding: start + 2,
|
|
2124
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2125
|
+
sampler: { type: "filtering" }
|
|
2126
|
+
},
|
|
2127
|
+
{
|
|
2128
|
+
binding: start + 3,
|
|
2129
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2130
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2131
|
+
},
|
|
2132
|
+
{
|
|
2133
|
+
binding: start + 4,
|
|
2134
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2135
|
+
sampler: { type: "non-filtering" }
|
|
2136
|
+
},
|
|
2137
|
+
{
|
|
2138
|
+
binding: start + 5,
|
|
2139
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2140
|
+
texture: { sampleType: "unfilterable-float", viewDimension: "2d" }
|
|
2141
|
+
}
|
|
2142
|
+
];
|
|
2143
|
+
}
|
|
2144
|
+
function physicalTextureFields(paramSchema) {
|
|
2145
|
+
return standardPhysicalTextureFields(paramSchema);
|
|
2146
|
+
}
|
|
2147
|
+
function appendTextureInjection(_bgl, fields) {
|
|
2148
|
+
const fieldSet = new Set(fields);
|
|
2149
|
+
return standardPhysicalTextureFields(
|
|
2150
|
+
STANDARD_PIPELINE_PARAM_SCHEMA.concat(
|
|
2151
|
+
fields.map((name) => ({ name, type: "texture2d" }))
|
|
2152
|
+
)
|
|
2153
|
+
).flatMap((field) => {
|
|
2154
|
+
if (!fieldSet.has(field)) return [];
|
|
2155
|
+
const canonicalIndex = STANDARD_PHYSICAL_TEXTURE_FIELDS.indexOf(field);
|
|
2156
|
+
const binding = 26 + canonicalIndex * 2;
|
|
2157
|
+
return [
|
|
2158
|
+
{
|
|
2159
|
+
binding,
|
|
2160
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2161
|
+
sampler: { type: "filtering" }
|
|
2162
|
+
},
|
|
2163
|
+
{
|
|
2164
|
+
binding: binding + 1,
|
|
2165
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2166
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2167
|
+
}
|
|
2168
|
+
];
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
function materialBindGroupLayoutIdentity(shaderId, paramSchema) {
|
|
2172
|
+
const descriptor = buildBindGroupLayoutDescriptor(
|
|
2173
|
+
{
|
|
2174
|
+
shader: { id: shaderId, passKind: "forward", variantSet: void 0 },
|
|
2175
|
+
attachments: { colorFormats: [], depthFormat: void 0, sampleCount: 1 }},
|
|
2176
|
+
{ kind: "pbr-material-merged", materialParamSchema: paramSchema }
|
|
2177
|
+
);
|
|
2178
|
+
return JSON.stringify({
|
|
2179
|
+
entries: descriptor.entries,
|
|
2180
|
+
physicalTextureFields: physicalTextureFields(paramSchema)
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2183
|
+
function buildPbrViewBglEntries(caps) {
|
|
2184
|
+
const entries = [
|
|
2185
|
+
{
|
|
2186
|
+
binding: 0,
|
|
2187
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2188
|
+
// View captures use the same bind group with a per-face view slot.
|
|
2189
|
+
// Keeping this dynamic is also valid for the display slot at offset 0.
|
|
2190
|
+
buffer: { type: "uniform", hasDynamicOffset: true }
|
|
2191
|
+
},
|
|
2192
|
+
{
|
|
2193
|
+
binding: 3,
|
|
2194
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2195
|
+
texture: { sampleType: "depth", viewDimension: "2d" }
|
|
2196
|
+
},
|
|
2197
|
+
{
|
|
2198
|
+
binding: 4,
|
|
2199
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2200
|
+
sampler: { type: "comparison" }
|
|
2201
|
+
},
|
|
2202
|
+
// feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: point shadow
|
|
2203
|
+
// cube_array depth atlas. Bound to either the real ShadowAtlas
|
|
2204
|
+
// cube_array view (when point shadows are active) or a 1x1x6 fallback
|
|
2205
|
+
// cube_array view cleared to 1.0 (fully lit). Visibility is FRAGMENT
|
|
2206
|
+
// only -- the directional binding 3 is VERTEX|FRAGMENT for shadow
|
|
2207
|
+
// probe-debug sampling, but the cube atlas has no host-side probe path.
|
|
2208
|
+
{
|
|
2209
|
+
binding: 5,
|
|
2210
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2211
|
+
texture: { sampleType: "depth", viewDimension: "cube-array" }
|
|
2212
|
+
},
|
|
2213
|
+
// feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: point shadow
|
|
2214
|
+
// params UBO. Carries `array<vec4<f32>, 4>` = 64 B with one lane per
|
|
2215
|
+
// shadow-casting point light slot (shadowAtlasLayer in [0, 4)). Each
|
|
2216
|
+
// lane stores `(near, far, depthBias, normalBias)` so the fragment-shader
|
|
2217
|
+
// depth-ref reconstruction (lighting-punctual.wgsl evalPointShadowed)
|
|
2218
|
+
// can avoid sampling DirectLightSlot for the URP path. The shared
|
|
2219
|
+
// DirectLightSlot metadata remains the identity owner, so binding 6 is
|
|
2220
|
+
// unused on HDRP shaders even though the BGL declares it (charter P4 single SSOT
|
|
2221
|
+
// BGL across pipelines; the HDRP variant simply doesn't reference the
|
|
2222
|
+
// binding in WGSL, which is allowed).
|
|
2223
|
+
{
|
|
2224
|
+
binding: 6,
|
|
2225
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2226
|
+
buffer: { type: "uniform" }
|
|
2227
|
+
},
|
|
2228
|
+
// feat-20260613-csm-cascaded-shadow-maps M5 / w28: shadowCasterCascade
|
|
2229
|
+
// UBO (16 B). Carries the 0-based cascade index of the shadow pass
|
|
2230
|
+
// currently being rasterized so `shadow_caster.wgsl` can index into
|
|
2231
|
+
// `view.lightViewProj_X` per cascade. Shifted from binding 5 to
|
|
2232
|
+
// binding 7 on 2026-06-13 to make room for point-shadow bindings 5/6
|
|
2233
|
+
// (they predate this feat in main; CSM's slot was the optimal-yield
|
|
2234
|
+
// give since point-shadow needs FRAGMENT-only and the cascade UBO
|
|
2235
|
+
// needs vertex-stage too — keeping cascade higher avoids interleaving
|
|
2236
|
+
// visibility flags within the contiguous shadow-binding cluster).
|
|
2237
|
+
{
|
|
2238
|
+
binding: 7,
|
|
2239
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2240
|
+
buffer: { type: "uniform" }
|
|
2241
|
+
},
|
|
2242
|
+
// feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5): spot shadow
|
|
2243
|
+
// atlas. A single `texture_depth_2d` holding up to 4 spot shadows in a 2x2
|
|
2244
|
+
// tile grid (urp-pipeline.ts spotShadowDepth). FRAGMENT-only — the spot
|
|
2245
|
+
// shadow factor is reconstructed at fragment time via perspective-divide in
|
|
2246
|
+
// `evalSpotShadowed` (lighting-punctual.wgsl).
|
|
2247
|
+
//
|
|
2248
|
+
// ALWAYS-ON (no caps gate, unlike the point cube_array atlas at binding 5
|
|
2249
|
+
// which rides POINT_SHADOW_AVAILABLE): spot uses `texture_depth_2d` which is
|
|
2250
|
+
// compat-safe in every WebGPU profile, so the binding is unconditionally
|
|
2251
|
+
// declared. The matching WGSL declaration is `spotShadowMap` at @group(0)
|
|
2252
|
+
// binding 8 in common.wgsl (also unconditional) — the two must stay in
|
|
2253
|
+
// lock-step or WebGPU validation rejects the bind group at smoke time
|
|
2254
|
+
// (memory: BGL shape mismatch is a browser-path-only bug). No binding 9
|
|
2255
|
+
// sampler: spot reuses the comparison sampler at binding 4.
|
|
2256
|
+
// feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5): spot shadow 2D
|
|
2257
|
+
// atlas, the LAST view-BG binding. The per-spot fragment-read perspective
|
|
2258
|
+
// lightViewProj matrices that w24 originally declared at a standalone
|
|
2259
|
+
// binding 9 uniform buffer were folded into the View UBO (binding 0,
|
|
2260
|
+
// `view.spotLightViewProj`) in w25 (scope-amend webkit-fallback): the
|
|
2261
|
+
// standalone binding pushed the WebGL2 fallback fragment uniform-buffer
|
|
2262
|
+
// count to 12, over GLES 3.0's `max_uniform_buffers_per_shader_stage = 11`,
|
|
2263
|
+
// crashing pipeline-layout creation on the compat path (this feat's target).
|
|
2264
|
+
{
|
|
2265
|
+
binding: 8,
|
|
2266
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2267
|
+
texture: { sampleType: "depth", viewDimension: "2d" }
|
|
2268
|
+
}
|
|
2269
|
+
];
|
|
2270
|
+
const extendedLighting = caps.extendedLighting ?? true;
|
|
2271
|
+
const lowLimitCloudBindings = extendedLighting === false && caps.projectorAvailable === false;
|
|
2272
|
+
if (extendedLighting) {
|
|
2273
|
+
entries.push(
|
|
2274
|
+
{
|
|
2275
|
+
binding: 9,
|
|
2276
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2277
|
+
sampler: { type: "filtering" }
|
|
2278
|
+
},
|
|
2279
|
+
{
|
|
2280
|
+
binding: 11,
|
|
2281
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2282
|
+
texture: { sampleType: "float", viewDimension: "2d-array" }
|
|
2283
|
+
},
|
|
2284
|
+
{
|
|
2285
|
+
binding: 12,
|
|
2286
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2287
|
+
texture: { sampleType: "float", viewDimension: "2d-array" }
|
|
2288
|
+
},
|
|
2289
|
+
{
|
|
2290
|
+
binding: 13,
|
|
2291
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2292
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2293
|
+
},
|
|
2294
|
+
{
|
|
2295
|
+
binding: 14,
|
|
2296
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2297
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2298
|
+
},
|
|
2299
|
+
{
|
|
2300
|
+
binding: 15,
|
|
2301
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2302
|
+
buffer: { type: "uniform" }
|
|
2303
|
+
}
|
|
2304
|
+
);
|
|
2305
|
+
} else if (caps.projectorAvailable !== false) {
|
|
2306
|
+
entries.push(
|
|
2307
|
+
{
|
|
2308
|
+
binding: 11,
|
|
2309
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2310
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2311
|
+
},
|
|
2312
|
+
{
|
|
2313
|
+
binding: 12,
|
|
2314
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2315
|
+
sampler: { type: "filtering" }
|
|
2316
|
+
}
|
|
2317
|
+
);
|
|
2318
|
+
}
|
|
2319
|
+
entries.push({
|
|
2320
|
+
binding: 10,
|
|
2321
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2322
|
+
buffer: { type: "uniform", hasDynamicOffset: true }
|
|
2323
|
+
});
|
|
2324
|
+
if (!lowLimitCloudBindings) {
|
|
2325
|
+
entries.push(
|
|
2326
|
+
{
|
|
2327
|
+
binding: 16,
|
|
2328
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2329
|
+
texture: { sampleType: "float", viewDimension: "2d" }
|
|
2330
|
+
},
|
|
2331
|
+
{
|
|
2332
|
+
binding: 17,
|
|
2333
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2334
|
+
sampler: { type: "filtering" }
|
|
2335
|
+
}
|
|
2336
|
+
);
|
|
2337
|
+
}
|
|
2338
|
+
return entries;
|
|
2339
|
+
}
|
|
2340
|
+
function buildPbrPipelineLayouts(device, caps) {
|
|
2341
|
+
const viewBglRes = device.createBindGroupLayout(
|
|
2342
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: "pbr-view", caps })
|
|
2343
|
+
);
|
|
2344
|
+
if (!viewBglRes.ok) throw viewBglRes.error;
|
|
2345
|
+
const materialBglRes = device.createBindGroupLayout(
|
|
2346
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
2347
|
+
kind: "pbr-material-merged",
|
|
2348
|
+
caps
|
|
2349
|
+
})
|
|
2350
|
+
);
|
|
2351
|
+
if (!materialBglRes.ok) throw materialBglRes.error;
|
|
2352
|
+
const meshArrayBglRes = device.createBindGroupLayout(
|
|
2353
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: "pbr-mesh-array", caps })
|
|
2354
|
+
);
|
|
2355
|
+
if (!meshArrayBglRes.ok) throw meshArrayBglRes.error;
|
|
2356
|
+
const instancesBglRes = device.createBindGroupLayout(
|
|
2357
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
2358
|
+
kind: "pbr-instances",
|
|
2359
|
+
caps: { ...caps, probeBlend: false }
|
|
2360
|
+
})
|
|
2361
|
+
);
|
|
2362
|
+
if (!instancesBglRes.ok) throw instancesBglRes.error;
|
|
2363
|
+
const probeInstancesBglRes = caps.storageBuffer ? device.createBindGroupLayout(
|
|
2364
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
2365
|
+
kind: "pbr-instances",
|
|
2366
|
+
caps: { ...caps, probeBlend: true }
|
|
2367
|
+
})
|
|
2368
|
+
) : { ok: true, value: instancesBglRes.value };
|
|
2369
|
+
if (!probeInstancesBglRes.ok) throw probeInstancesBglRes.error;
|
|
2370
|
+
const layouts = [
|
|
2371
|
+
viewBglRes.value,
|
|
2372
|
+
materialBglRes.value,
|
|
2373
|
+
meshArrayBglRes.value,
|
|
2374
|
+
instancesBglRes.value
|
|
2375
|
+
];
|
|
2376
|
+
const pipelineLayoutRes = device.createPipelineLayout({
|
|
2377
|
+
label: "pbr-pl",
|
|
2378
|
+
bindGroupLayouts: layouts
|
|
2379
|
+
});
|
|
2380
|
+
if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
|
|
2381
|
+
const probeLayouts = [viewBglRes.value, materialBglRes.value, meshArrayBglRes.value, probeInstancesBglRes.value];
|
|
2382
|
+
let probePipelineLayout = null;
|
|
2383
|
+
if (caps.storageBuffer) {
|
|
2384
|
+
const probePipelineLayoutRes = device.createPipelineLayout({
|
|
2385
|
+
label: "pbr-probe-pl",
|
|
2386
|
+
bindGroupLayouts: probeLayouts
|
|
2387
|
+
});
|
|
2388
|
+
if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;
|
|
2389
|
+
probePipelineLayout = probePipelineLayoutRes.value;
|
|
2390
|
+
}
|
|
2391
|
+
return {
|
|
2392
|
+
pipelineLayout: pipelineLayoutRes.value,
|
|
2393
|
+
viewBgl: viewBglRes.value,
|
|
2394
|
+
materialBgl: materialBglRes.value,
|
|
2395
|
+
meshArrayBgl: meshArrayBglRes.value,
|
|
2396
|
+
instancesBgl: instancesBglRes.value,
|
|
2397
|
+
probeInstancesBgl: probeInstancesBglRes.value,
|
|
2398
|
+
probePipelineLayout,
|
|
2399
|
+
bindGroupLayouts: layouts
|
|
2400
|
+
};
|
|
2401
|
+
}
|
|
2402
|
+
var SKIN_MATERIAL_SHADER_ID = "forgeax::pbr-skin";
|
|
2403
|
+
var SHADOW_CASTER_SHADER_ID = "forgeax::default-shadow-caster";
|
|
2404
|
+
var AUTHORED_STANDARD_ID_RE = /::(?:standard|pbr-skin)(?:-|$)/;
|
|
2405
|
+
function isStandardPbrSkinMaterialShader(shaderId) {
|
|
2406
|
+
return shaderId === SKIN_MATERIAL_SHADER_ID || shaderId === "forgeax::default-standard-pbr-skin" || shaderId !== void 0 && /::pbr-skin(?:-|$)/.test(shaderId);
|
|
2407
|
+
}
|
|
2408
|
+
function shadowCasterVariantSet(storageBuffer, skinned, gpuDrivenSceneIndex = false, alphaMask = false, vertexColorAvailable = false) {
|
|
2409
|
+
const skinningDisabled = !skinned;
|
|
2410
|
+
const defines = {
|
|
2411
|
+
ALPHA_MASK: alphaMask,
|
|
2412
|
+
GPU_DRIVEN_SCENE_INDEX_AVAILABLE: gpuDrivenSceneIndex,
|
|
2413
|
+
GPU_DRIVEN_SCENE_INDEX_EXPLICIT: false,
|
|
2414
|
+
SKINNING_DISABLED: skinningDisabled,
|
|
2415
|
+
STORAGE_BUFFER_AVAILABLE: storageBuffer
|
|
2416
|
+
};
|
|
2417
|
+
if (vertexColorAvailable) defines.VERTEX_COLOR_AVAILABLE = true;
|
|
2418
|
+
return Object.entries(defines).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([name, value]) => `${name}=${String(value)}`).join("+");
|
|
2419
|
+
}
|
|
2420
|
+
function resolvePipelineGroup2Contract(source) {
|
|
2421
|
+
const withoutComments = source.replace(/\/\*[\s\S]*?\*\//gu, "").replace(/\/\/.*$/gmu, "");
|
|
2422
|
+
const bindings = [
|
|
2423
|
+
...withoutComments.matchAll(/@group\s*\(\s*2\s*\)\s*@binding\s*\(\s*(\d+)\s*\)/gu)
|
|
2424
|
+
].map((match) => Number(match[1]));
|
|
2425
|
+
const hasSkinBindings = bindings.includes(1) || bindings.includes(2);
|
|
2426
|
+
const hasClusterBindings = bindings.some((binding) => binding >= 3);
|
|
2427
|
+
if (hasSkinBindings && hasClusterBindings) return "skin-cluster";
|
|
2428
|
+
if (hasSkinBindings) return "skin";
|
|
2429
|
+
if (hasClusterBindings) return "cluster";
|
|
2430
|
+
return "mesh";
|
|
2431
|
+
}
|
|
2432
|
+
function isStandardPbrMaterialShader(shaderId) {
|
|
2433
|
+
return shaderId === "forgeax::default-standard-pbr" || shaderId === SKIN_MATERIAL_SHADER_ID || shaderId === "forgeax::default-standard-pbr-skin" || shaderId !== void 0 && AUTHORED_STANDARD_ID_RE.test(shaderId);
|
|
2434
|
+
}
|
|
2435
|
+
function isCanonicalStandardPbrMaterialShader(shaderId) {
|
|
2436
|
+
return shaderId === "forgeax::default-standard-pbr" || shaderId === SKIN_MATERIAL_SHADER_ID || shaderId === "forgeax::default-standard-pbr-skin";
|
|
2437
|
+
}
|
|
2438
|
+
function buildPbrSkinLayouts(device, caps, pbr) {
|
|
2439
|
+
const skinMeshArrayBglRes = device.createBindGroupLayout(
|
|
2440
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
2441
|
+
kind: "pbr-skin-mesh-array",
|
|
2442
|
+
caps
|
|
2443
|
+
})
|
|
2444
|
+
);
|
|
2445
|
+
if (!skinMeshArrayBglRes.ok) throw skinMeshArrayBglRes.error;
|
|
2446
|
+
const layouts = [
|
|
2447
|
+
pbr.viewBgl,
|
|
2448
|
+
pbr.materialBgl,
|
|
2449
|
+
skinMeshArrayBglRes.value,
|
|
2450
|
+
pbr.instancesBgl
|
|
2451
|
+
];
|
|
2452
|
+
const pipelineLayoutRes = device.createPipelineLayout({
|
|
2453
|
+
label: "pbr-skin-pl",
|
|
2454
|
+
bindGroupLayouts: layouts
|
|
2455
|
+
});
|
|
2456
|
+
if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
|
|
2457
|
+
const probeLayouts = [pbr.viewBgl, pbr.materialBgl, skinMeshArrayBglRes.value, pbr.probeInstancesBgl];
|
|
2458
|
+
let probePipelineLayout = null;
|
|
2459
|
+
if (caps.storageBuffer) {
|
|
2460
|
+
const probePipelineLayoutRes = device.createPipelineLayout({
|
|
2461
|
+
label: "pbr-skin-probe-pl",
|
|
2462
|
+
bindGroupLayouts: probeLayouts
|
|
2463
|
+
});
|
|
2464
|
+
if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;
|
|
2465
|
+
probePipelineLayout = probePipelineLayoutRes.value;
|
|
2466
|
+
}
|
|
2467
|
+
return {
|
|
2468
|
+
pipelineLayout: pipelineLayoutRes.value,
|
|
2469
|
+
viewBgl: pbr.viewBgl,
|
|
2470
|
+
materialBgl: pbr.materialBgl,
|
|
2471
|
+
meshArrayBgl: skinMeshArrayBglRes.value,
|
|
2472
|
+
instancesBgl: pbr.instancesBgl,
|
|
2473
|
+
probeInstancesBgl: pbr.probeInstancesBgl,
|
|
2474
|
+
probePipelineLayout,
|
|
2475
|
+
bindGroupLayouts: layouts
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2478
|
+
function buildGpuDrivenPbrInstancesBindGroupLayout(device, caps) {
|
|
2479
|
+
if (!caps.storageBuffer) {
|
|
2480
|
+
throw new Error("GPU-driven PBR instances layout requires storage-buffer capability");
|
|
2481
|
+
}
|
|
2482
|
+
const result = device.createBindGroupLayout(
|
|
2483
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
2484
|
+
kind: "pbr-gpu-driven-instances",
|
|
2485
|
+
caps
|
|
2486
|
+
})
|
|
2487
|
+
);
|
|
2488
|
+
if (!result.ok) throw result.error;
|
|
2489
|
+
return result.value;
|
|
2490
|
+
}
|
|
2491
|
+
function buildSurfaceDirectInstancesBindGroupLayout(device, caps) {
|
|
2492
|
+
if (!caps.storageBuffer) {
|
|
2493
|
+
throw new Error("Direct Surface instances layout requires storage-buffer capability");
|
|
2494
|
+
}
|
|
2495
|
+
const result = device.createBindGroupLayout(
|
|
2496
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
2497
|
+
kind: "pbr-surface-direct-instances",
|
|
2498
|
+
caps
|
|
2499
|
+
})
|
|
2500
|
+
);
|
|
2501
|
+
if (!result.ok) throw result.error;
|
|
2502
|
+
return result.value;
|
|
2503
|
+
}
|
|
2504
|
+
function buildGpuDrivenPbrPipelineLayout(device, pbr, gpuDrivenInstancesBgl) {
|
|
2505
|
+
const result = device.createPipelineLayout({
|
|
2506
|
+
label: "pbr-gpu-driven-pl",
|
|
2507
|
+
bindGroupLayouts: [pbr.viewBgl, pbr.materialBgl, pbr.meshArrayBgl, gpuDrivenInstancesBgl]
|
|
2508
|
+
});
|
|
2509
|
+
if (!result.ok) throw result.error;
|
|
2510
|
+
return result.value;
|
|
2511
|
+
}
|
|
2512
|
+
function buildGpuDrivenPbrSkinPipelineLayout(device, pbrSkin, gpuDrivenInstancesBgl) {
|
|
2513
|
+
const result = device.createPipelineLayout({
|
|
2514
|
+
label: "pbr-skin-gpu-driven-pl",
|
|
2515
|
+
bindGroupLayouts: [
|
|
2516
|
+
pbrSkin.viewBgl,
|
|
2517
|
+
pbrSkin.materialBgl,
|
|
2518
|
+
pbrSkin.meshArrayBgl,
|
|
2519
|
+
gpuDrivenInstancesBgl
|
|
2520
|
+
]
|
|
2521
|
+
});
|
|
2522
|
+
if (!result.ok) throw result.error;
|
|
2523
|
+
return result.value;
|
|
2524
|
+
}
|
|
2525
|
+
function createPbrSkinMeshBindGroupEntries(meshBuffer, meshSize, paletteBuffer, paletteWindowBytes) {
|
|
2526
|
+
return [
|
|
2527
|
+
{
|
|
2528
|
+
binding: 0,
|
|
2529
|
+
resource: { kind: "buffer", value: { buffer: meshBuffer, offset: 0, size: meshSize } }
|
|
2530
|
+
},
|
|
2531
|
+
...[1, 2].map((binding) => ({
|
|
2532
|
+
binding,
|
|
2533
|
+
resource: {
|
|
2534
|
+
kind: "buffer",
|
|
2535
|
+
value: {
|
|
2536
|
+
buffer: paletteBuffer,
|
|
2537
|
+
offset: 0,
|
|
2538
|
+
size: paletteWindowBytes
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
}))
|
|
2542
|
+
];
|
|
2543
|
+
}
|
|
2544
|
+
function pbrSkinMeshDynamicOffsets(meshOffset, paletteOffset) {
|
|
2545
|
+
return [meshOffset, paletteOffset, paletteOffset];
|
|
2546
|
+
}
|
|
2547
|
+
var SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET = "";
|
|
2548
|
+
function createHdrpBindGroupLayoutDescriptor() {
|
|
2549
|
+
const meshBufType = "read-only-storage";
|
|
2550
|
+
const clusterBufType = "read-only-storage";
|
|
2551
|
+
return {
|
|
2552
|
+
label: "hdrp-unified-bgl-group2",
|
|
2553
|
+
entries: [
|
|
2554
|
+
{
|
|
2555
|
+
binding: 0,
|
|
2556
|
+
// Standard fragment lighting (transmission/refraction and clustered
|
|
2557
|
+
// evaluation) reads the same mesh transform window as the vertex
|
|
2558
|
+
// stage. Keep this visibility in the HDRP descriptor aligned with
|
|
2559
|
+
// the URP mesh-array descriptor; restricting it to vertex makes the
|
|
2560
|
+
// HDRP pipeline invalid when fs_main accesses `meshes[0]`.
|
|
2561
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2562
|
+
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
2563
|
+
},
|
|
2564
|
+
// Bindings 1 and 2 stay absent for the URP physical isolation gap.
|
|
2565
|
+
{
|
|
2566
|
+
binding: 3,
|
|
2567
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2568
|
+
buffer: { type: clusterBufType, hasDynamicOffset: false }
|
|
2569
|
+
},
|
|
2570
|
+
{
|
|
2571
|
+
binding: 4,
|
|
2572
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2573
|
+
buffer: { type: clusterBufType, hasDynamicOffset: false }
|
|
2574
|
+
},
|
|
2575
|
+
{
|
|
2576
|
+
binding: 5,
|
|
2577
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2578
|
+
buffer: { type: clusterBufType, hasDynamicOffset: false }
|
|
2579
|
+
},
|
|
2580
|
+
{
|
|
2581
|
+
binding: 6,
|
|
2582
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2583
|
+
buffer: { type: "uniform", hasDynamicOffset: false }
|
|
2584
|
+
},
|
|
2585
|
+
{
|
|
2586
|
+
binding: 7,
|
|
2587
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2588
|
+
texture: { sampleType: "float", viewDimension: "2d", multisampled: false }
|
|
2589
|
+
},
|
|
2590
|
+
{
|
|
2591
|
+
binding: 8,
|
|
2592
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2593
|
+
sampler: { type: "filtering" }
|
|
2594
|
+
}
|
|
2595
|
+
]
|
|
2596
|
+
};
|
|
2597
|
+
}
|
|
2598
|
+
function createHdrpSkinBindGroupLayoutDescriptor() {
|
|
2599
|
+
const base = createHdrpBindGroupLayoutDescriptor();
|
|
2600
|
+
const baseEntries = base.entries;
|
|
2601
|
+
if (baseEntries === void 0 || baseEntries[0] === void 0) {
|
|
2602
|
+
throw new Error("HDRP base group(2) layout must declare mesh binding 0");
|
|
2603
|
+
}
|
|
2604
|
+
const paletteType = "read-only-storage";
|
|
2605
|
+
return {
|
|
2606
|
+
label: "hdrp-skin-unified-bgl-group2",
|
|
2607
|
+
entries: [
|
|
2608
|
+
baseEntries[0],
|
|
2609
|
+
{
|
|
2610
|
+
binding: 1,
|
|
2611
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2612
|
+
buffer: { type: paletteType, hasDynamicOffset: true }
|
|
2613
|
+
},
|
|
2614
|
+
{
|
|
2615
|
+
binding: 2,
|
|
2616
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2617
|
+
buffer: { type: paletteType, hasDynamicOffset: true }
|
|
2618
|
+
},
|
|
2619
|
+
...baseEntries.slice(1)
|
|
2620
|
+
]
|
|
2621
|
+
};
|
|
2622
|
+
}
|
|
2623
|
+
function resolveMaterialParamSchema(spec, options) {
|
|
2624
|
+
if (options.materialParamSchema !== void 0) return options.materialParamSchema;
|
|
2625
|
+
if (options.registry !== void 0) {
|
|
2626
|
+
const lookup = options.registry.findMaterialArtifact(spec.shader.id);
|
|
2627
|
+
if (lookup.ok) return lookup.value.paramSchema;
|
|
2628
|
+
}
|
|
2629
|
+
return void 0;
|
|
2630
|
+
}
|
|
2631
|
+
function buildBindGroupLayoutDescriptor(spec, options) {
|
|
2632
|
+
switch (options.kind) {
|
|
2633
|
+
case "pbr-view": {
|
|
2634
|
+
const caps = options.caps ?? { };
|
|
2635
|
+
return {
|
|
2636
|
+
label: "pbr-view-bgl",
|
|
2637
|
+
entries: buildPbrViewBglEntries(caps)
|
|
2638
|
+
};
|
|
2639
|
+
}
|
|
2640
|
+
case "pbr-mesh-array": {
|
|
2641
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
2642
|
+
const meshBufType = caps.storageBuffer ? "read-only-storage" : "uniform";
|
|
2643
|
+
return {
|
|
2644
|
+
label: "pbr-mesh-array-bgl",
|
|
2645
|
+
entries: [
|
|
2646
|
+
{
|
|
2647
|
+
binding: 0,
|
|
2648
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2649
|
+
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
2650
|
+
}
|
|
2651
|
+
]
|
|
2652
|
+
};
|
|
2653
|
+
}
|
|
2654
|
+
case "pbr-instances": {
|
|
2655
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
2656
|
+
const meshBufType = caps.storageBuffer ? "read-only-storage" : "uniform";
|
|
2657
|
+
const entries = [
|
|
2658
|
+
{
|
|
2659
|
+
binding: 0,
|
|
2660
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2661
|
+
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
2662
|
+
},
|
|
2663
|
+
...caps.probeBlend === true ? [
|
|
2664
|
+
{
|
|
2665
|
+
// Per-object fragment lane; the record is always exactly 160B.
|
|
2666
|
+
binding: 1,
|
|
2667
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2668
|
+
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
2669
|
+
}
|
|
2670
|
+
] : []
|
|
2671
|
+
];
|
|
2672
|
+
return {
|
|
2673
|
+
label: caps.probeBlend === true ? "pbr-probe-instances-bgl" : "pbr-instances-bgl",
|
|
2674
|
+
entries: entries.map(
|
|
2675
|
+
(entry) => entry.binding === 0 ? {
|
|
2676
|
+
...entry,
|
|
2677
|
+
// Standard transmission reads the same per-instance transform in
|
|
2678
|
+
// fs_main to convert glTF unit-space thickness into world metres.
|
|
2679
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT
|
|
2680
|
+
} : entry
|
|
2681
|
+
)
|
|
2682
|
+
};
|
|
2683
|
+
}
|
|
2684
|
+
case "pbr-gpu-driven-instances": {
|
|
2685
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
2686
|
+
const meshBufType = caps.storageBuffer ? "read-only-storage" : "uniform";
|
|
2687
|
+
return {
|
|
2688
|
+
label: "pbr-gpu-driven-instances-bgl",
|
|
2689
|
+
entries: [
|
|
2690
|
+
{
|
|
2691
|
+
binding: 0,
|
|
2692
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2693
|
+
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
2694
|
+
},
|
|
2695
|
+
{
|
|
2696
|
+
// ShadowCaster's scene-index entry still reads the visible row
|
|
2697
|
+
// through binding(1). Keep this alias in the dedicated layout so
|
|
2698
|
+
// the shared visible bind group can serve both the Standard PBR
|
|
2699
|
+
// (binding(2)) and depth-only shadow (binding(1)) consumers.
|
|
2700
|
+
binding: 1,
|
|
2701
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2702
|
+
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
2703
|
+
},
|
|
2704
|
+
{
|
|
2705
|
+
binding: 2,
|
|
2706
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2707
|
+
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
2708
|
+
},
|
|
2709
|
+
{
|
|
2710
|
+
// Generic Surface dynamic pages are read by authored Surface
|
|
2711
|
+
// accessors. The binding is present for every scene-index group
|
|
2712
|
+
// so Standard and custom Surface batches share one owner shape.
|
|
2713
|
+
binding: 3,
|
|
2714
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2715
|
+
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
2716
|
+
},
|
|
2717
|
+
{
|
|
2718
|
+
// Frame time, explicit event ranges, and paired background/depth
|
|
2719
|
+
// facts use separate read-only pages. This keeps live state out
|
|
2720
|
+
// of the material row and leaves skin's address lane untouched.
|
|
2721
|
+
binding: 4,
|
|
2722
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2723
|
+
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
2724
|
+
},
|
|
2725
|
+
{
|
|
2726
|
+
// Frame time is one frame-global fact. Keeping it outside the
|
|
2727
|
+
// member row prevents a stable frame from issuing one 4-byte
|
|
2728
|
+
// queue write for every visible Surface member.
|
|
2729
|
+
binding: 5,
|
|
2730
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2731
|
+
buffer: { type: "uniform", hasDynamicOffset: false }
|
|
2732
|
+
}
|
|
2733
|
+
]
|
|
2734
|
+
};
|
|
2735
|
+
}
|
|
2736
|
+
case "pbr-surface-direct-instances": {
|
|
2737
|
+
return {
|
|
2738
|
+
label: "pbr-surface-direct-instances-bgl",
|
|
2739
|
+
entries: [
|
|
2740
|
+
{
|
|
2741
|
+
binding: 0,
|
|
2742
|
+
// Direct instance transforms are consumed only by vs_main. Keep
|
|
2743
|
+
// them out of the fragment-stage storage budget; Surface already
|
|
2744
|
+
// needs the retained ProbeBlend/page/frame records there and the
|
|
2745
|
+
// portable WebGPU limit is eight storage buffers per stage.
|
|
2746
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2747
|
+
buffer: { type: "read-only-storage", hasDynamicOffset: false }
|
|
2748
|
+
},
|
|
2749
|
+
{
|
|
2750
|
+
binding: 1,
|
|
2751
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2752
|
+
buffer: { type: "read-only-storage", hasDynamicOffset: true }
|
|
2753
|
+
},
|
|
2754
|
+
{
|
|
2755
|
+
binding: 3,
|
|
2756
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2757
|
+
buffer: { type: "read-only-storage", hasDynamicOffset: false }
|
|
2758
|
+
},
|
|
2759
|
+
{
|
|
2760
|
+
binding: 4,
|
|
2761
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2762
|
+
buffer: { type: "read-only-storage", hasDynamicOffset: false }
|
|
2763
|
+
},
|
|
2764
|
+
{
|
|
2765
|
+
binding: 5,
|
|
2766
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2767
|
+
buffer: { type: "uniform", hasDynamicOffset: false }
|
|
2768
|
+
},
|
|
2769
|
+
{
|
|
2770
|
+
binding: 6,
|
|
2771
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2772
|
+
buffer: { type: "uniform", hasDynamicOffset: false }
|
|
2773
|
+
}
|
|
2774
|
+
]
|
|
2775
|
+
};
|
|
2776
|
+
}
|
|
2777
|
+
case "pbr-skin-mesh-array": {
|
|
2778
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
2779
|
+
const meshBufType = caps.storageBuffer ? "read-only-storage" : "uniform";
|
|
2780
|
+
return {
|
|
2781
|
+
label: "pbr-skin-mesh-array-bgl",
|
|
2782
|
+
entries: [
|
|
2783
|
+
{
|
|
2784
|
+
binding: 0,
|
|
2785
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2786
|
+
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
2787
|
+
},
|
|
2788
|
+
{
|
|
2789
|
+
binding: 1,
|
|
2790
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2791
|
+
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
2792
|
+
},
|
|
2793
|
+
{
|
|
2794
|
+
binding: 2,
|
|
2795
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
2796
|
+
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
2797
|
+
}
|
|
2798
|
+
]
|
|
2799
|
+
};
|
|
2800
|
+
}
|
|
2801
|
+
case "pbr-material-merged": {
|
|
2802
|
+
const resolvedSchema = resolveMaterialParamSchema(spec, options);
|
|
2803
|
+
const effectiveSchema = resolvedSchema ?? STANDARD_PIPELINE_PARAM_SCHEMA;
|
|
2804
|
+
const physicalFields = physicalTextureFields(effectiveSchema);
|
|
2805
|
+
const userRegionSchema = isCanonicalStandardPbrMaterialShader(spec.shader.id) ? STANDARD_PIPELINE_PARAM_SCHEMA : effectiveSchema;
|
|
2806
|
+
const userRegion = buildPbrMaterialUserRegionEntries(userRegionSchema);
|
|
2807
|
+
const afterIbl = [...userRegion, ...appendInjection(userRegion, "ibl")];
|
|
2808
|
+
const afterTransmission = [...afterIbl, ...appendInjection(afterIbl, "transmission")];
|
|
2809
|
+
const engineRegion = options.caps?.transmissionBackdrop === false && spec.shader.id !== "forgeax::single-layer-medium" ? afterIbl : afterTransmission;
|
|
2810
|
+
const afterSurfaceMedium = spec.shader.id === "forgeax::single-layer-medium" ? [...engineRegion, ...appendSingleLayerMediumInjection(engineRegion)] : engineRegion;
|
|
2811
|
+
const merged = [
|
|
2812
|
+
...afterSurfaceMedium,
|
|
2813
|
+
...appendTextureInjection(afterSurfaceMedium, physicalFields)
|
|
2814
|
+
];
|
|
2815
|
+
if (options.caps?.storageBuffer ?? true) {
|
|
2816
|
+
merged.push({
|
|
2817
|
+
binding: 46,
|
|
2818
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
2819
|
+
buffer: { type: "read-only-storage", hasDynamicOffset: false }
|
|
2820
|
+
});
|
|
2821
|
+
}
|
|
2822
|
+
const entries = [
|
|
2823
|
+
...merged,
|
|
2824
|
+
...spec.shader.id === "forgeax::single-layer-medium" ? [] : [
|
|
2825
|
+
{
|
|
2826
|
+
binding: 47,
|
|
2827
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2828
|
+
texture: { sampleType: "float", viewDimension: "cube" }
|
|
2829
|
+
}
|
|
2830
|
+
]
|
|
2831
|
+
];
|
|
2832
|
+
return {
|
|
2833
|
+
label: "pbr-material-skylight-bgl",
|
|
2834
|
+
entries
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
case "unlit-material": {
|
|
2838
|
+
const resolvedSchema = resolveMaterialParamSchema(spec, options);
|
|
2839
|
+
return {
|
|
2840
|
+
label: "unlit-material-bgl",
|
|
2841
|
+
entries: buildPbrMaterialUserRegionEntries(resolvedSchema)
|
|
2842
|
+
};
|
|
2843
|
+
}
|
|
2844
|
+
case "hdrp-7-slot": {
|
|
2845
|
+
const desc = createHdrpBindGroupLayoutDescriptor();
|
|
2846
|
+
return {
|
|
2847
|
+
label: desc.label ?? "hdrp-unified-bgl-group2",
|
|
2848
|
+
entries: [...desc.entries ?? []]
|
|
2849
|
+
};
|
|
2850
|
+
}
|
|
2851
|
+
case "fullscreen-post": {
|
|
2852
|
+
return {
|
|
2853
|
+
label: "fullscreen-post-bgl",
|
|
2854
|
+
entries: buildFullscreenPostInputEntries(spec)
|
|
2855
|
+
};
|
|
2856
|
+
}
|
|
2857
|
+
case "fullscreen-post-with-params": {
|
|
2858
|
+
return {
|
|
2859
|
+
label: "fullscreen-post-with-params-bgl",
|
|
2860
|
+
entries: [
|
|
2861
|
+
...buildFullscreenPostInputEntries(spec),
|
|
2862
|
+
{
|
|
2863
|
+
binding: 2,
|
|
2864
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2865
|
+
buffer: { type: "uniform" }
|
|
2866
|
+
}
|
|
2867
|
+
]
|
|
2868
|
+
};
|
|
2869
|
+
}
|
|
2870
|
+
case "fullscreen-post-with-scene-depth": {
|
|
2871
|
+
return {
|
|
2872
|
+
label: "fullscreen-post-with-scene-depth-bgl",
|
|
2873
|
+
entries: [
|
|
2874
|
+
...buildFullscreenPostInputEntries(spec),
|
|
2875
|
+
{
|
|
2876
|
+
binding: 2,
|
|
2877
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2878
|
+
buffer: { type: "uniform" }
|
|
2879
|
+
},
|
|
2880
|
+
{
|
|
2881
|
+
binding: 3,
|
|
2882
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2883
|
+
texture: { sampleType: "depth", viewDimension: "2d" }
|
|
2884
|
+
},
|
|
2885
|
+
{
|
|
2886
|
+
binding: 4,
|
|
2887
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2888
|
+
sampler: { type: "non-filtering" }
|
|
2889
|
+
}
|
|
2890
|
+
]
|
|
2891
|
+
};
|
|
2892
|
+
}
|
|
2893
|
+
case "fullscreen-post-with-scene-depth-msaa": {
|
|
2894
|
+
return {
|
|
2895
|
+
label: "fullscreen-post-with-scene-depth-msaa-bgl",
|
|
2896
|
+
entries: [
|
|
2897
|
+
...buildFullscreenPostInputEntries(spec),
|
|
2898
|
+
{
|
|
2899
|
+
binding: 2,
|
|
2900
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2901
|
+
buffer: { type: "uniform" }
|
|
2902
|
+
},
|
|
2903
|
+
{
|
|
2904
|
+
binding: 3,
|
|
2905
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2906
|
+
texture: { sampleType: "depth", viewDimension: "2d", multisampled: true }
|
|
2907
|
+
},
|
|
2908
|
+
{
|
|
2909
|
+
binding: 4,
|
|
2910
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2911
|
+
sampler: { type: "non-filtering" }
|
|
2912
|
+
}
|
|
2913
|
+
]
|
|
2914
|
+
};
|
|
2915
|
+
}
|
|
2916
|
+
case "fullscreen-post-with-paired-msaa": {
|
|
2917
|
+
return {
|
|
2918
|
+
label: "fullscreen-post-with-paired-msaa-bgl",
|
|
2919
|
+
entries: [
|
|
2920
|
+
{
|
|
2921
|
+
binding: 0,
|
|
2922
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2923
|
+
texture: {
|
|
2924
|
+
sampleType: "unfilterable-float",
|
|
2925
|
+
viewDimension: "2d",
|
|
2926
|
+
multisampled: true
|
|
2927
|
+
}
|
|
2928
|
+
},
|
|
2929
|
+
{
|
|
2930
|
+
binding: 1,
|
|
2931
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2932
|
+
sampler: { type: "filtering" }
|
|
2933
|
+
},
|
|
2934
|
+
{
|
|
2935
|
+
binding: 2,
|
|
2936
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2937
|
+
buffer: { type: "uniform" }
|
|
2938
|
+
},
|
|
2939
|
+
{
|
|
2940
|
+
binding: 3,
|
|
2941
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2942
|
+
texture: { sampleType: "depth", viewDimension: "2d", multisampled: true }
|
|
2943
|
+
},
|
|
2944
|
+
{
|
|
2945
|
+
binding: 4,
|
|
2946
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2947
|
+
sampler: { type: "non-filtering" }
|
|
2948
|
+
}
|
|
2949
|
+
]
|
|
2950
|
+
};
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
function buildFullscreenPostInputEntries(spec) {
|
|
2955
|
+
const inputFormat = spec.attachments.depthFormat ?? spec.attachments.colorFormats[0];
|
|
2956
|
+
const sampleType = inputFormat === "depth32float" || inputFormat === "depth24plus" || inputFormat === "depth24plus-stencil8" || inputFormat === "depth16unorm" ? "depth" : inputFormat === "r32float" ? "unfilterable-float" : "float";
|
|
2957
|
+
return [
|
|
2958
|
+
{
|
|
2959
|
+
binding: 0,
|
|
2960
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2961
|
+
texture: { sampleType, viewDimension: "2d" }
|
|
2962
|
+
},
|
|
2963
|
+
{
|
|
2964
|
+
binding: 1,
|
|
2965
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
2966
|
+
sampler: {
|
|
2967
|
+
type: sampleType === "depth" ? "comparison" : "filtering"
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
];
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2973
|
+
// src/systems/pass-selector.ts
|
|
2974
|
+
function matchPass(tags, selector) {
|
|
2975
|
+
if (Object.keys(selector).length === 0) return true;
|
|
2976
|
+
for (const [key, allowedValues] of Object.entries(selector)) {
|
|
2977
|
+
const passValue = tags[key];
|
|
2978
|
+
if (passValue === void 0) return false;
|
|
2979
|
+
if (allowedValues.length === 0) return false;
|
|
2980
|
+
if (!allowedValues.includes(passValue)) return false;
|
|
2981
|
+
}
|
|
2982
|
+
return true;
|
|
2983
|
+
}
|
|
2984
|
+
function selectPasses(passes, selector) {
|
|
2985
|
+
if (Object.keys(selector).length === 0) return passes;
|
|
2986
|
+
return passes.filter(
|
|
2987
|
+
(p) => matchPass(p.renderState?.tags ?? {}, selector)
|
|
2988
|
+
);
|
|
2989
|
+
}
|
|
2990
|
+
|
|
2991
|
+
// src/gpu-driven/prepared-draw.ts
|
|
2992
|
+
function failure(code, detail) {
|
|
2993
|
+
return { ok: false, error: new GpuDrivenPreparationError(code, detail) };
|
|
2994
|
+
}
|
|
2995
|
+
function hasRequiredVertexInputs(expected, actual) {
|
|
2996
|
+
return expected.every(
|
|
2997
|
+
(input) => actual.some(
|
|
2998
|
+
(candidate) => candidate.semantic === input.semantic && candidate.location === input.location && candidate.format === input.format
|
|
2999
|
+
)
|
|
3000
|
+
);
|
|
3001
|
+
}
|
|
3002
|
+
function hasMaterialResources(snapshot, receipt) {
|
|
3003
|
+
if ((snapshot.material.textureSources?.size ?? 0) > 0 || (snapshot.material.videoTextureFields?.size ?? 0) > 0) {
|
|
3004
|
+
return false;
|
|
3005
|
+
}
|
|
3006
|
+
const textures = snapshot.material.textureHandles;
|
|
3007
|
+
const samplers = snapshot.material.samplerHandles;
|
|
3008
|
+
const authoredTextures = snapshot.material.authoredTextureFields;
|
|
3009
|
+
const authoredSamplers = snapshot.material.authoredSamplerFields;
|
|
3010
|
+
return receipt.resourceSlots.every((slot) => {
|
|
3011
|
+
if (slot.kind === "storage-buffer") {
|
|
3012
|
+
return receipt.surface?.dynamicInput?.group === slot.group && receipt.surface.dynamicInput.binding === slot.binding && slot.group === 3 && slot.binding === 3;
|
|
3013
|
+
}
|
|
3014
|
+
if (slot.kind === "texture") {
|
|
3015
|
+
if (!authoredTextures?.has(slot.parameter)) return true;
|
|
3016
|
+
return textures?.has(slot.parameter) === true || snapshot.material.textureSources?.has(slot.parameter) === true || snapshot.material.videoTextureFields?.has(slot.parameter) === true;
|
|
3017
|
+
}
|
|
3018
|
+
if (!authoredSamplers?.has(slot.parameter)) return true;
|
|
3019
|
+
return samplers?.has(slot.parameter) === true;
|
|
3020
|
+
});
|
|
3021
|
+
}
|
|
3022
|
+
function prepareGpuDrivenDraw(input) {
|
|
3023
|
+
const receipt = input.artifact.receipt;
|
|
3024
|
+
if (receipt === void 0) {
|
|
3025
|
+
return failure("missing-material-receipt", {
|
|
3026
|
+
reason: "material-receipt-missing",
|
|
3027
|
+
owner: "material",
|
|
3028
|
+
expected: "MaterialShaderArtifact.receipt"
|
|
3029
|
+
});
|
|
3030
|
+
}
|
|
3031
|
+
if (receipt.generation !== input.generation) {
|
|
3032
|
+
return failure("stale-generation", {
|
|
3033
|
+
reason: "generation-stale",
|
|
3034
|
+
owner: "generation",
|
|
3035
|
+
expectedGeneration: input.generation,
|
|
3036
|
+
actualGeneration: receipt.generation
|
|
3037
|
+
});
|
|
3038
|
+
}
|
|
3039
|
+
if (receipt.reflection.layoutIdentity !== input.artifact.layoutIdentity) {
|
|
3040
|
+
return failure("reflection-mismatch", {
|
|
3041
|
+
reason: "reflection-receipt-mismatch",
|
|
3042
|
+
owner: "material",
|
|
3043
|
+
expected: input.artifact.layoutIdentity,
|
|
3044
|
+
actual: receipt.reflection.layoutIdentity
|
|
3045
|
+
});
|
|
3046
|
+
}
|
|
3047
|
+
if (receipt.uvSets.some((uv) => uv.set > 0) && input.geometry.vertexInputs.length < 3) {
|
|
3048
|
+
return failure("missing-uv", {
|
|
3049
|
+
reason: "uv-set-missing",
|
|
3050
|
+
owner: "geometry",
|
|
3051
|
+
expected: `${receipt.uvSets.length} material UV sets`,
|
|
3052
|
+
actual: `${input.geometry.vertexInputs.filter((vertex) => vertex.semantic.startsWith("uv")).length} geometry UV sets`
|
|
3053
|
+
});
|
|
3054
|
+
}
|
|
3055
|
+
if (!hasRequiredVertexInputs(receipt.vertexInputs, input.geometry.vertexInputs)) {
|
|
3056
|
+
return failure("vertex-input-mismatch", {
|
|
3057
|
+
reason: "vertex-semantic-mismatch",
|
|
3058
|
+
owner: "geometry",
|
|
3059
|
+
expected: receipt.vertexInputs.map((input2) => input2.semantic).join(","),
|
|
3060
|
+
actual: input.geometry.vertexInputs.map((input2) => input2.semantic).join(",")
|
|
3061
|
+
});
|
|
3062
|
+
}
|
|
3063
|
+
const hasAlphaMask = receipt.alphaMask.cutoff.length > 0 || receipt.alphaMask.source.length > 0;
|
|
3064
|
+
if (hasAlphaMask && (receipt.alphaMask.cutoff.length === 0 || receipt.alphaMask.source.length === 0)) {
|
|
3065
|
+
return failure("alpha-mask-mismatch", {
|
|
3066
|
+
reason: "alpha-mask-receipt-missing",
|
|
3067
|
+
owner: "material",
|
|
3068
|
+
expected: "alphaMask.cutoff and alphaMask.source for a masked Pass"
|
|
3069
|
+
});
|
|
3070
|
+
}
|
|
3071
|
+
if (!hasMaterialResources(input.snapshot, receipt)) {
|
|
3072
|
+
return failure("resource-not-ready", {
|
|
3073
|
+
reason: "material-resource-missing",
|
|
3074
|
+
owner: "material",
|
|
3075
|
+
expected: receipt.resourceSlots.map((slot) => slot.parameter).join(",")
|
|
3076
|
+
});
|
|
3077
|
+
}
|
|
3078
|
+
const deformation = input.snapshot.skin === void 0 ? "rigid" : "skin";
|
|
3079
|
+
if (deformation === "skin") {
|
|
3080
|
+
if (input.skinReceipt === void 0 || receipt.skinPaletteAddress === void 0) {
|
|
3081
|
+
return failure("skin-receipt-mismatch", {
|
|
3082
|
+
reason: "skin-address-missing",
|
|
3083
|
+
owner: "skin",
|
|
3084
|
+
expected: "skinPaletteAddress and skinReceipt"
|
|
3085
|
+
});
|
|
3086
|
+
}
|
|
3087
|
+
if (input.skinReceipt.identity !== input.snapshot.skin?.identity || input.skinReceipt.generation !== input.snapshot.skin?.generation || input.skinReceipt.group !== receipt.skinPaletteAddress.group || input.skinReceipt.binding !== receipt.skinPaletteAddress.binding) {
|
|
3088
|
+
return failure("skin-receipt-mismatch", {
|
|
3089
|
+
reason: "skin-address-missing",
|
|
3090
|
+
owner: "skin",
|
|
3091
|
+
expected: `${receipt.skinPaletteAddress.group}:${receipt.skinPaletteAddress.binding}@${input.snapshot.skin?.generation ?? "<missing>"}`,
|
|
3092
|
+
actual: `${input.skinReceipt.group}:${input.skinReceipt.binding}@${input.skinReceipt.generation}`
|
|
3093
|
+
});
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
return {
|
|
3097
|
+
ok: true,
|
|
3098
|
+
value: {
|
|
3099
|
+
identity: {
|
|
3100
|
+
material: input.artifact.material,
|
|
3101
|
+
geometry: input.geometry.identity,
|
|
3102
|
+
deformation
|
|
3103
|
+
},
|
|
3104
|
+
receiptGeneration: receipt.generation,
|
|
3105
|
+
receiptIdentity: receipt.receiptIdentity,
|
|
3106
|
+
directEntry: receipt.directEntry,
|
|
3107
|
+
sceneIndexEntry: receipt.sceneIndexEntry,
|
|
3108
|
+
materialRow: receipt.materialRow,
|
|
3109
|
+
resourceSlots: receipt.resourceSlots,
|
|
3110
|
+
uvSets: receipt.uvSets,
|
|
3111
|
+
vertexInputs: receipt.vertexInputs,
|
|
3112
|
+
alphaMask: receipt.alphaMask,
|
|
3113
|
+
skinPaletteAddress: receipt.skinPaletteAddress,
|
|
3114
|
+
topology: input.draw.topology,
|
|
3115
|
+
indexed: input.draw.kind === "indexed",
|
|
3116
|
+
first: input.draw.first,
|
|
3117
|
+
count: input.draw.count,
|
|
3118
|
+
baseVertex: input.draw.baseVertex
|
|
3119
|
+
}
|
|
3120
|
+
};
|
|
3121
|
+
}
|
|
3122
|
+
|
|
3123
|
+
// src/extract/gpu-driven.ts
|
|
3124
|
+
function gpuDrivenDrawKey(worldEntity, materialHandle, drawItemIndex) {
|
|
3125
|
+
return `${worldEntity}:${materialHandle}:${drawItemIndex}`;
|
|
3126
|
+
}
|
|
3127
|
+
function gpuDrivenShadowDrawKey(worldEntity, materialHandle, drawItemIndex, passIndex) {
|
|
3128
|
+
return `${gpuDrivenDrawKey(worldEntity, materialHandle, drawItemIndex)}:${passIndex}`;
|
|
3129
|
+
}
|
|
3130
|
+
function gpuDrivenMaterialArtifactKey(input) {
|
|
3131
|
+
return [
|
|
3132
|
+
input.material,
|
|
3133
|
+
input.deformation,
|
|
3134
|
+
input.receiptIdentity ?? "<legacy-receipt>",
|
|
3135
|
+
input.receiptGeneration
|
|
3136
|
+
].join("|");
|
|
3137
|
+
}
|
|
3138
|
+
function gpuDrivenSourceDrawItemIndex(draw, compactIndex) {
|
|
3139
|
+
return draw.drawItemIndex ?? compactIndex;
|
|
3140
|
+
}
|
|
3141
|
+
function resolvePreparedGpuDrivenDraw(input) {
|
|
3142
|
+
return prepareGpuDrivenDraw(input);
|
|
3143
|
+
}
|
|
3144
|
+
function gpuDrivenMaterialResourceClass(material) {
|
|
3145
|
+
const textures = [...material.textureHandles?.entries() ?? []].map(([name, handle]) => [name, Number(handle)]).sort(([left], [right]) => left.localeCompare(right));
|
|
3146
|
+
const samplers = [...material.samplerHandles?.entries() ?? []].map(([name, handle]) => [name, Number(handle)]).sort(([left], [right]) => left.localeCompare(right));
|
|
3147
|
+
return JSON.stringify({
|
|
3148
|
+
textures,
|
|
3149
|
+
samplers
|
|
3150
|
+
});
|
|
3151
|
+
}
|
|
3152
|
+
function hasCpuOnlyMaterialResources(material) {
|
|
3153
|
+
return (material.textureSources?.size ?? 0) > 0 || (material.videoTextureFields?.size ?? 0) > 0;
|
|
3154
|
+
}
|
|
3155
|
+
function buildGpuDrivenDraws(input) {
|
|
3156
|
+
const legacy = "submeshes" in input;
|
|
3157
|
+
if (!legacy && input.mesh === void 0) return [];
|
|
3158
|
+
const parsedMesh = legacy ? void 0 : input.mesh;
|
|
3159
|
+
if (!legacy && parsedMesh === void 0) return [];
|
|
3160
|
+
const indexed = legacy ? input.indexed : parsedMesh?.indices !== void 0;
|
|
3161
|
+
const submeshes = legacy ? input.submeshes : parsedMesh?.submeshes ?? [];
|
|
3162
|
+
const layoutProjection = parsedMesh === void 0 ? void 0 : deriveVertexLayoutProjection(parsedMesh.attributes);
|
|
3163
|
+
const geometry = {
|
|
3164
|
+
identity: parsedMesh === void 0 ? "<no-mesh>" : `${parsedMesh.guid ?? "<no-guid>"}:${layoutProjection?.digest ?? ""}`,
|
|
3165
|
+
vertexInputs: (layoutProjection?.attributes ?? []).map((attribute) => ({
|
|
3166
|
+
semantic: attribute.key,
|
|
3167
|
+
location: attribute.shaderLocation,
|
|
3168
|
+
format: attribute.format
|
|
3169
|
+
})),
|
|
3170
|
+
topology: submeshes[0]?.topology ?? "triangle-list",
|
|
3171
|
+
indexed
|
|
3172
|
+
};
|
|
3173
|
+
let nonIndexedFirst = 0;
|
|
3174
|
+
return submeshes.flatMap((submesh, drawItemIndex) => {
|
|
3175
|
+
const drawMaterial = input.materials[submesh.materialSlot] ?? input.fallbackMaterial;
|
|
3176
|
+
const first = indexed ? submesh.indexOffset : nonIndexedFirst;
|
|
3177
|
+
nonIndexedFirst += submesh.vertexCount;
|
|
3178
|
+
if (drawMaterial.transparent === true) return [];
|
|
3179
|
+
const draw = {
|
|
3180
|
+
drawItemIndex,
|
|
3181
|
+
kind: indexed ? "indexed" : "non-indexed",
|
|
3182
|
+
first,
|
|
3183
|
+
count: indexed ? submesh.indexCount : submesh.vertexCount,
|
|
3184
|
+
baseVertex: 0,
|
|
3185
|
+
materialSlot: submesh.materialSlot,
|
|
3186
|
+
topology: submesh.topology,
|
|
3187
|
+
pipelineClass: `${drawMaterial.materialShaderId ?? "forgeax::default-unlit"}|${submesh.topology}|${JSON.stringify(drawMaterial.renderState ?? null)}`,
|
|
3188
|
+
materialResourceClass: gpuDrivenMaterialResourceClass(drawMaterial)
|
|
3189
|
+
};
|
|
3190
|
+
const lodRanges = !legacy ? input.lodMeshes?.map((lodMesh) => {
|
|
3191
|
+
if (lodMesh === void 0) return void 0;
|
|
3192
|
+
const lower = lodMesh.submeshes[drawItemIndex];
|
|
3193
|
+
if (lower === void 0) return void 0;
|
|
3194
|
+
const lowerIndexed = lodMesh.indices !== void 0;
|
|
3195
|
+
const lowerFirst = lowerIndexed ? lower.indexOffset : lodMesh.submeshes.slice(0, drawItemIndex).reduce((offset, entry) => offset + entry.vertexCount, 0);
|
|
3196
|
+
return {
|
|
3197
|
+
first: lowerFirst,
|
|
3198
|
+
count: lowerIndexed ? lower.indexCount : lower.vertexCount,
|
|
3199
|
+
baseVertex: 0
|
|
3200
|
+
};
|
|
3201
|
+
}) : void 0;
|
|
3202
|
+
const withLodRanges = lodRanges?.length !== 0 && lodRanges?.every((range) => range !== void 0) ? { lodRanges } : {};
|
|
3203
|
+
const prepared = legacy ? input.prepare?.(draw, drawMaterial) : hasCpuOnlyMaterialResources(drawMaterial) ? void 0 : (() => {
|
|
3204
|
+
const materialShaderId = drawMaterial.materialShaderId;
|
|
3205
|
+
const vertexColorAvailable = geometry.vertexInputs.some(
|
|
3206
|
+
(input2) => input2.semantic === "color"
|
|
3207
|
+
);
|
|
3208
|
+
const sceneIndexProgramKey = Object.entries(
|
|
3209
|
+
drawMaterial.materialSceneIndexProgramKeys ?? {}
|
|
3210
|
+
).find(
|
|
3211
|
+
([passName, program]) => program.pass === "forward" && drawMaterial.materialProgramKeys?.[passName] === materialShaderId
|
|
3212
|
+
)?.[1]?.specializationKey;
|
|
3213
|
+
const artifact = materialShaderId === void 0 ? void 0 : input.getMaterialShaderArtifact?.(sceneIndexProgramKey ?? materialShaderId, {
|
|
3214
|
+
vertexColorAvailable,
|
|
3215
|
+
deformation: input.baseSnapshot.skin === void 0 ? "rigid" : "skin",
|
|
3216
|
+
pass: "forward",
|
|
3217
|
+
address: "scene-index"
|
|
3218
|
+
});
|
|
3219
|
+
const requiresReceipt = isCanonicalStandardPbrMaterialShader(materialShaderId) || sceneIndexProgramKey !== void 0;
|
|
3220
|
+
if (artifact === void 0) {
|
|
3221
|
+
return input.getMaterialShaderArtifact !== void 0 && requiresReceipt ? new GpuDrivenPreparationError("missing-material-receipt", {
|
|
3222
|
+
reason: "material-receipt-missing",
|
|
3223
|
+
owner: "material",
|
|
3224
|
+
expected: `artifact for ${materialShaderId}`
|
|
3225
|
+
}) : void 0;
|
|
3226
|
+
}
|
|
3227
|
+
const receipt = artifact.receipt;
|
|
3228
|
+
if (receipt === void 0) {
|
|
3229
|
+
return new GpuDrivenPreparationError("missing-material-receipt", {
|
|
3230
|
+
reason: "material-receipt-missing",
|
|
3231
|
+
owner: "material",
|
|
3232
|
+
expected: `receipt for ${materialShaderId}`
|
|
3233
|
+
});
|
|
3234
|
+
}
|
|
3235
|
+
const skinReceipt = input.baseSnapshot.skin !== void 0 && receipt.skinPaletteAddress !== void 0 ? {
|
|
3236
|
+
identity: input.baseSnapshot.skin.identity,
|
|
3237
|
+
generation: input.baseSnapshot.skin.generation,
|
|
3238
|
+
group: receipt.skinPaletteAddress.group,
|
|
3239
|
+
binding: receipt.skinPaletteAddress.binding,
|
|
3240
|
+
byteOffset: input.baseSnapshot.skin.byteOffset
|
|
3241
|
+
} : void 0;
|
|
3242
|
+
const selectedArtifact = artifact === void 0 || sceneIndexProgramKey === void 0 || materialShaderId === void 0 ? artifact : {
|
|
3243
|
+
...artifact,
|
|
3244
|
+
material: materialShaderId,
|
|
3245
|
+
specializationKey: sceneIndexProgramKey
|
|
3246
|
+
};
|
|
3247
|
+
const result = resolvePreparedGpuDrivenDraw({
|
|
3248
|
+
snapshot: { ...input.baseSnapshot, material: drawMaterial },
|
|
3249
|
+
artifact: selectedArtifact ?? artifact,
|
|
3250
|
+
geometry: { ...geometry, topology: draw.topology, indexed: draw.kind === "indexed" },
|
|
3251
|
+
generation: receipt.generation,
|
|
3252
|
+
draw,
|
|
3253
|
+
...skinReceipt === void 0 ? {} : { skinReceipt }
|
|
3254
|
+
});
|
|
3255
|
+
return result.ok ? result.value : result.error;
|
|
3256
|
+
})();
|
|
3257
|
+
if (prepared instanceof GpuDrivenPreparationError) {
|
|
3258
|
+
return [{ ...draw, preparationError: prepared, ...withLodRanges }];
|
|
3259
|
+
}
|
|
3260
|
+
return [
|
|
3261
|
+
prepared === void 0 ? { ...draw, ...withLodRanges } : { ...draw, prepared, ...withLodRanges }
|
|
3262
|
+
];
|
|
3263
|
+
});
|
|
3264
|
+
}
|
|
3265
|
+
|
|
3266
|
+
export { AtmosphereInvalidParameterError, AutoExposureCapabilityUnavailableError, AutoExposureInvalidParameterError, AutoExposureStageFailedError, AutoExposureStaleGenerationError, BarrelDistortionInvalidParameterError, COOKIE_MATRIX_BYTES, COOKIE_SLICE_CAPACITY, COOKIE_SLICE_SIZE, DEFAULT_MOTION_BLUR_PARAMS, DeviceScope, DynamicResolutionInvalidParameterError, DynamicResolutionRequiresTaaError, DynamicResolutionTimingUnavailableError, EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES, EXTENDED_LIGHTING_TOPOLOGY, EnvironmentGenerationFailedError, EnvironmentSourceConflictError, EquirectProjectionFailedError, FXAA_POST_PROCESS_ID, FogCardinalityError, FrameReceiptStaleError, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_COPY_SRC, GPU_BUFFER_USAGE_INDEX, GPU_BUFFER_USAGE_INDIRECT, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_STORAGE, GPU_BUFFER_USAGE_UNIFORM, GPU_BUFFER_USAGE_VERTEX, GPU_SHADER_STAGE_COMPUTE, GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_COPY_SRC, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT_AND_TEXTURE_BINDING, GPU_TEXTURE_USAGE_STORAGE_BINDING, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GpuDrivenPreparationError, IES_SLICE_CAPACITY, IES_SLICE_HEIGHT, IES_SLICE_WIDTH, InstanceProjectionStore, InstanceTransformsError, LifecycleTransaction, MOTION_BLUR_PARAMS_BYTE_SIZE, MaterialSkinAttrMissingError, MotionBlurValidationError, ObservationUnavailableError, OwnerStageFailedError, PointShadowAtlasBoundsViolationError, PointShadowAtlasUninitializedError, PointsLinesBudgetExceededError, PointsLinesInvalidStyleError, PointsLinesMaterialUnsupportedError, PointsLinesPrepareFailedError, PointsLinesStyleUnsupportedError, PointsLinesTopologyMismatchError, RENDER_PHASE_CATALOG, RenderFeatureCapabilityMissingError, RenderFeatureDrawRecordingFailedError, RenderFeaturePreparationFailedError, RenderFeaturePreparedStateMismatchError, RenderFeatureRegistrationConflictError, RenderFeatureStageFailedError, RenderIntentInvalidError, RenderTargetCapabilityMissingError, RenderTargetDescriptorInvalidError, RenderTargetOperationFailedError, RenderTargetStateInvalidError, RendererContractFailureError, RendererOperationError, SHADOW_ATLAS_DEFAULT_FACE_SIZE, SHADOW_ATLAS_DEFAULT_LAYERS, SHADOW_CASTER_SHADER_ID, SKIN_MATERIAL_SHADER_ID, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, SceneDataUnavailableError, ShadowAtlas, ShadowInvalidConfigError, SkinMaterialMismatchError, SkinPaletteOverflowError, StandardClusterIndexOverflowError, StandardClusterTransportUnavailableError, StandardLightBudgetExceededError, StandardProfileInvalidError, TaaCapsInsufficientError, TemporalFrameSubmitError, TransmissionCapabilityMissingError, VertexColorVariantConflictError, VideoUploadUnsupportedError, VolumeDensityShapeMismatchError, VolumeInvalidBoundsError, VolumeInvalidParametersError, VolumeOwnerConflictError, buildBindGroupLayoutDescriptor, buildGpuDrivenDraws, buildGpuDrivenPbrInstancesBindGroupLayout, buildGpuDrivenPbrPipelineLayout, buildGpuDrivenPbrSkinPipelineLayout, buildPbrMaterialUserRegionEntries, buildPbrPipelineLayouts, buildPbrSkinLayouts, buildSurfaceDirectInstancesBindGroupLayout, createAutoExposureError, createAutoExposureInspection, createHdrpBindGroupLayoutDescriptor, createHdrpSkinBindGroupLayoutDescriptor, createLightResourceUnavailable, createPbrSkinMeshBindGroupEntries, createRenderTargetMaterialSource, createVisibilityBudget, deriveExtendedLightingCapability, effectiveMotionBlurSampleCount, extendedLightingSampledTextureCapacityAvailable, getOpaqueResourceIdentity, getTextureIdentity, gpuDrivenDrawKey, gpuDrivenMaterialArtifactKey, gpuDrivenShadowDrawKey, gpuDrivenSourceDrawItemIndex, hasRequiredVertexInputs, instanceCollectionCacheKey, instanceUploadRangesForResident, isCanonicalStandardPbrMaterialShader, isMotionBlurIntervalValid, isStandardPbrMaterialShader, isStandardPbrSkinMaterialShader, makeZeroCameraFallbackSnapshot, matchPass, materialBindGroupLayoutIdentity, motionBlurExposureScale, motionBlurSampleDelta, motionBlurTemporalDemand, pbrSkinMeshDynamicOffsets, physicalTextureFields, renderTargetMaterialSourceIdentity, resolveMotionBlurParams, resolvePipelineGroup2Contract, resolveRenderTargetMaterialSource, selectPasses, shadowCasterVariantSet, validateGraphTargetCaptureReadback, validateInstanceTransforms, validateMotionBlurParams, worldEntityKey };
|
|
3267
|
+
//# sourceMappingURL=chunk-MXTWKZO4.mjs.map
|
|
3268
|
+
//# sourceMappingURL=chunk-MXTWKZO4.mjs.map
|