@forgeax/engine-render 0.1.33 → 0.1.34
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 +1010 -124
- 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/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 +3 -3
- 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/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 +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/barrel-distortion.d.ts +47 -0
- package/dist/barrel-distortion.d.ts.map +1 -0
- package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
- package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
- package/dist/{chunk-ZDQWGQW7.mjs → chunk-HEB564WF.mjs} +4 -4
- package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-HEB564WF.mjs.map} +1 -1
- package/dist/{chunk-VOZWDM3L.mjs → chunk-MKDIT2EM.mjs} +1307 -188
- package/dist/chunk-MKDIT2EM.mjs.map +1 -0
- package/dist/{chunk-LEAXOMYJ.mjs → chunk-OCDLEI6I.mjs} +3 -3
- package/dist/{chunk-LEAXOMYJ.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
- package/dist/chunk-ODZWR6JQ.mjs +4927 -0
- package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
- package/dist/{chunk-3RTCJTH4.mjs → chunk-SHFUFJ5N.mjs} +184 -13
- package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
- package/dist/{chunk-OO3DRYK7.mjs → chunk-UI5SFODX.mjs} +176 -96
- package/dist/chunk-UI5SFODX.mjs.map +1 -0
- package/dist/{chunk-PLAXOOX5.mjs → chunk-UINHLCZA.mjs} +561 -79
- package/dist/chunk-UINHLCZA.mjs.map +1 -0
- package/dist/{chunk-NB2S7ZRX.mjs → chunk-WEX45HKH.mjs} +127 -386
- package/dist/chunk-WEX45HKH.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 +6759 -2875
- package/dist/construct-renderer.mjs.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 +18 -4
- 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/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 +10 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/plan.d.ts +8 -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 +44 -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/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/skylight-bind-group.d.ts +10 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +27 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +258 -8
- 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 +48 -100
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +7 -7
- package/dist/pbr-pipeline.d.ts +19 -1
- 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/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/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 +37 -3
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +10 -61
- 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/main-pass-geometry.d.ts +21 -5
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +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/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 +22 -3
- 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/typed-frame-graph.d.ts +22 -2
- 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 +10 -0
- 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 +42 -4
- 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 +16 -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-residency.d.ts +12 -0
- package/dist/render-system-residency.d.ts.map +1 -0
- package/dist/render-system.d.ts +19 -14
- 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 +12 -5
- package/dist/scene/render-scene.d.ts.map +1 -1
- 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/temporal/gpu.d.ts +13 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- 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__/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-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 +2 -2
- 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__/main-pass-material-medium-selection.unit.test.ts +146 -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__/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 +58 -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 +7 -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 +41 -7
- 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/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 +3 -3
- 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 +41 -18
- package/src/assembly/render-feature-post-processes.ts +54 -0
- package/src/assembly/renderer-facade.ts +4 -1
- 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 +115 -61
- 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 +214 -252
- 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/dynamic-geometry.ts +12 -1
- package/src/errors/cloud.ts +103 -0
- package/src/errors/render.ts +44 -7
- 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/features/barrel-distortion.ts +172 -0
- package/src/features/error-reporting.ts +26 -6
- package/src/features/host.ts +115 -14
- package/src/features/plan.ts +8 -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 +47 -0
- package/src/fullscreen-post-process-pass.ts +41 -9
- 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/skylight-bind-group.ts +49 -7
- package/src/index.ts +196 -9
- package/src/inspection-types.ts +162 -0
- package/src/instance-buffer-cache.ts +4 -4
- package/src/instances.ts +149 -569
- package/src/pbr-pipeline.ts +219 -13
- 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/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/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
- 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__/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 +852 -0
- package/src/record/fold-instance-buffer.ts +51 -0
- package/src/record/frame-lighting.ts +36 -2
- package/src/record/frame-snapshot.ts +39 -3
- package/src/record/frame.ts +217 -1084
- package/src/record/gpu-draw-receipts.ts +38 -0
- package/src/record/gpu-timing.ts +48 -5
- package/src/record/main-pass-geometry.ts +251 -82
- package/src/record/main-pass-material.ts +66 -4
- package/src/record/main-pass-sprite-draws.ts +7 -65
- package/src/record/main-pass.ts +156 -20
- package/src/record/motion-blur-receipt.ts +91 -0
- package/src/record/probe-blend-buffer.ts +180 -0
- package/src/record/recovery-pipeline.ts +35 -3
- package/src/record/render-context.ts +39 -3
- package/src/record/shadow-pass.ts +30 -1
- package/src/record/skybox-post-pass.ts +28 -4
- package/src/record/typed-frame-graph.ts +770 -134
- package/src/record/view-ubo.ts +26 -3
- package/src/record/volume-params.ts +225 -0
- package/src/recovery/render-system-candidate.ts +235 -42
- package/src/reflection/record-owner.ts +7 -3
- package/src/render-contract.ts +48 -4
- package/src/render-graph-primitives.ts +7 -1
- package/src/render-pipeline.ts +130 -0
- package/src/render-system-extract-tail.ts +57 -61
- package/src/render-system-extract.ts +74 -76
- package/src/render-system-presentation.ts +56 -0
- package/src/render-system-producer-roots.ts +96 -0
- package/src/render-system-residency.ts +159 -0
- package/src/render-system.ts +347 -363
- package/src/scene/probe-blend.ts +96 -4
- package/src/scene/render-scene.ts +349 -280
- 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 +4 -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.map +0 -1
- 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.map +0 -1
- package/dist/chunk-VOZWDM3L.mjs.map +0 -1
package/src/instances.ts
CHANGED
|
@@ -1,52 +1,26 @@
|
|
|
1
|
+
import type { World } from '@forgeax/engine-ecs';
|
|
2
|
+
import { InstanceTransformsStrideMismatchError } from '@forgeax/engine-ecs/projection';
|
|
1
3
|
import type { RhiErrorCode } from '@forgeax/engine-rhi';
|
|
2
|
-
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
3
4
|
|
|
4
5
|
const MATRIX_STRIDE = 16;
|
|
5
|
-
const INITIAL_CAPACITY = 1;
|
|
6
6
|
|
|
7
|
+
/** Renderer projection identity; never stored in a World or SceneAsset. */
|
|
7
8
|
export type InstanceCollectionId = number & {
|
|
8
9
|
readonly __forgeaxInstanceCollectionId: unique symbol;
|
|
9
10
|
};
|
|
10
|
-
|
|
11
|
-
export interface InstanceCollectionData {
|
|
11
|
+
export interface InstanceCollectionInfo {
|
|
12
12
|
readonly collectionId: InstanceCollectionId;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface InstanceCollectionInfo extends InstanceCollectionData {
|
|
16
13
|
readonly count: number;
|
|
17
|
-
readonly capacity: number;
|
|
18
14
|
readonly revision: number;
|
|
19
15
|
}
|
|
20
|
-
|
|
21
16
|
export interface InstanceDirtyRange {
|
|
22
17
|
start: number;
|
|
23
18
|
end: number;
|
|
24
19
|
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Choose the ranges that initialize one resident GPU allocation.
|
|
28
|
-
*
|
|
29
|
-
* A cache miss is not a delta upload: recovery, reassociation, and any other
|
|
30
|
-
* new resident has uninitialized device memory. The canonical collection must
|
|
31
|
-
* therefore be copied in full even when the current authoring revision only
|
|
32
|
-
* records a partial dirty range. Existing residents keep the narrower ranges.
|
|
33
|
-
*/
|
|
34
|
-
export function instanceUploadRangesForResident(
|
|
35
|
-
activeIsNew: boolean,
|
|
36
|
-
dirtyRanges: readonly InstanceDirtyRange[],
|
|
37
|
-
fullRange: InstanceDirtyRange,
|
|
38
|
-
): readonly InstanceDirtyRange[] {
|
|
39
|
-
return activeIsNew ? [fullRange] : dirtyRanges;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
20
|
export interface InstanceCollectionSnapshot extends InstanceCollectionInfo {
|
|
43
21
|
readonly transforms: Float32Array;
|
|
44
|
-
/** Unique identity generations that travel with an instance through reorder. */
|
|
45
22
|
readonly generations: Uint32Array;
|
|
46
|
-
readonly dirtyRanges: readonly InstanceDirtyRange[];
|
|
47
23
|
}
|
|
48
|
-
|
|
49
|
-
/** The renderer-owned submission lane selected for one collection. */
|
|
50
24
|
export type InstanceSubmissionLane =
|
|
51
25
|
| 'unresident'
|
|
52
26
|
| 'direct-storage'
|
|
@@ -54,14 +28,8 @@ export type InstanceSubmissionLane =
|
|
|
54
28
|
| 'direct-uniform'
|
|
55
29
|
| 'chunked-uniform'
|
|
56
30
|
| 'unavailable';
|
|
57
|
-
|
|
58
|
-
/** Backend identity carried by collection residency and failure facts. */
|
|
59
31
|
export type InstanceBackendKind = 'webgpu' | 'wgpu-native' | 'wgpu-webgl2' | 'null' | 'unknown';
|
|
60
|
-
|
|
61
|
-
/** Closed record-stage failure vocabulary for collection residency. */
|
|
62
32
|
export type InstanceCollectionFailureCode = RhiErrorCode | 'queue-write-buffer-failed';
|
|
63
|
-
|
|
64
|
-
/** Typed producer facts retained when a collection cannot be admitted. */
|
|
65
33
|
export interface InstanceCollectionFailureFacts {
|
|
66
34
|
readonly requestedBytes: number;
|
|
67
35
|
readonly supportedBytes: number | undefined;
|
|
@@ -70,29 +38,9 @@ export interface InstanceCollectionFailureFacts {
|
|
|
70
38
|
readonly cause: string;
|
|
71
39
|
readonly recovery: string;
|
|
72
40
|
}
|
|
73
|
-
|
|
74
|
-
function instanceCollectionFailureFacts(
|
|
75
|
-
cause: string,
|
|
76
|
-
recovery: string,
|
|
77
|
-
requestedBytes = 0,
|
|
78
|
-
supportedBytes: number | undefined = undefined,
|
|
79
|
-
backend: InstanceBackendKind = 'unknown',
|
|
80
|
-
): InstanceCollectionFailureFacts {
|
|
81
|
-
return {
|
|
82
|
-
requestedBytes,
|
|
83
|
-
supportedBytes,
|
|
84
|
-
backend,
|
|
85
|
-
owner: 'renderer.instances',
|
|
86
|
-
cause,
|
|
87
|
-
recovery,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Detached, bounded collection evidence exposed by Renderer.inspect(). */
|
|
92
41
|
export interface InstanceCollectionInspection extends InstanceCollectionInfo {
|
|
93
42
|
readonly residentGeneration: number | undefined;
|
|
94
43
|
readonly lane: InstanceSubmissionLane;
|
|
95
|
-
readonly dirtyRanges: readonly InstanceDirtyRange[];
|
|
96
44
|
readonly uploadRanges: readonly InstanceDirtyRange[];
|
|
97
45
|
readonly uploadedBytes: number;
|
|
98
46
|
readonly requestedBytes: number;
|
|
@@ -109,82 +57,46 @@ export interface InstanceCollectionInspection extends InstanceCollectionInfo {
|
|
|
109
57
|
| undefined;
|
|
110
58
|
}
|
|
111
59
|
|
|
112
|
-
export
|
|
113
|
-
readonly transforms
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
export interface InstanceCollectionUpdateInput {
|
|
117
|
-
/** Matrix ordinal of the first matrix to replace. */
|
|
118
|
-
readonly start: number;
|
|
119
|
-
readonly transforms: Float32Array;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export interface InstanceCollectionInvalidDetail {
|
|
123
|
-
readonly collectionId?: number;
|
|
124
|
-
readonly operation: 'create' | 'replace' | 'update' | 'inspect' | 'release';
|
|
125
|
-
readonly expected: string;
|
|
126
|
-
readonly actual: number | string;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export type InstanceCollectionErrorCode =
|
|
130
|
-
| 'instance-collection-invalid'
|
|
131
|
-
| 'instance-collection-not-found'
|
|
132
|
-
| 'instance-collection-released';
|
|
133
|
-
|
|
134
|
-
export class InstanceCollectionError extends Error {
|
|
135
|
-
readonly code: InstanceCollectionErrorCode;
|
|
136
|
-
readonly expected: string;
|
|
137
|
-
readonly hint: string;
|
|
138
|
-
readonly detail: InstanceCollectionInvalidDetail | undefined;
|
|
139
|
-
readonly owner = 'renderer.instances' as const;
|
|
140
|
-
readonly recovery: string;
|
|
141
|
-
readonly facts: InstanceCollectionFailureFacts;
|
|
142
|
-
|
|
60
|
+
export class InstanceTransformsError extends Error {
|
|
61
|
+
readonly code = 'instance-transforms-invalid' as const;
|
|
62
|
+
readonly expected = 'finite column-major mat4 values, with transforms.length a multiple of 16';
|
|
63
|
+
readonly hint = 'repair Instances.transforms in the World or source SceneAsset and retry';
|
|
143
64
|
constructor(
|
|
144
|
-
|
|
145
|
-
expected: string,
|
|
146
|
-
hint: string,
|
|
147
|
-
detail?: InstanceCollectionInvalidDetail,
|
|
148
|
-
facts?: InstanceCollectionFailureFacts,
|
|
65
|
+
readonly detail: { readonly actualLength: number; readonly nonFiniteIndex?: number },
|
|
149
66
|
) {
|
|
150
|
-
super(
|
|
151
|
-
this.name = '
|
|
152
|
-
this.code = code;
|
|
153
|
-
this.expected = expected;
|
|
154
|
-
this.hint = hint;
|
|
155
|
-
this.detail = detail;
|
|
156
|
-
this.facts =
|
|
157
|
-
facts ??
|
|
158
|
-
instanceCollectionFailureFacts(
|
|
159
|
-
code,
|
|
160
|
-
hint,
|
|
161
|
-
detail?.operation === 'create' || detail?.operation === 'replace'
|
|
162
|
-
? typeof detail.actual === 'number' && Number.isFinite(detail.actual)
|
|
163
|
-
? detail.actual * Float32Array.BYTES_PER_ELEMENT
|
|
164
|
-
: 0
|
|
165
|
-
: 0,
|
|
166
|
-
);
|
|
167
|
-
this.recovery = this.facts.recovery;
|
|
67
|
+
super('Instances.transforms must contain complete finite matrices');
|
|
68
|
+
this.name = 'InstanceTransformsError';
|
|
168
69
|
}
|
|
169
70
|
}
|
|
71
|
+
export function validateInstanceTransforms(
|
|
72
|
+
transforms: ArrayLike<number>,
|
|
73
|
+
): InstanceTransformsError | InstanceTransformsStrideMismatchError | undefined {
|
|
74
|
+
if (transforms.length % MATRIX_STRIDE !== 0)
|
|
75
|
+
return new InstanceTransformsStrideMismatchError(transforms.length);
|
|
76
|
+
for (let index = 0; index < transforms.length; index++) {
|
|
77
|
+
if (!Number.isFinite(transforms[index]))
|
|
78
|
+
return new InstanceTransformsError({
|
|
79
|
+
actualLength: transforms.length,
|
|
80
|
+
nonFiniteIndex: index,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
170
85
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
readonly
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
capacity: number;
|
|
179
|
-
revision: number;
|
|
180
|
-
dirtyRanges: InstanceDirtyRange[];
|
|
181
|
-
/** Last revision detached for extraction; repeated reads of that revision
|
|
182
|
-
* retain the same ranges for multiple entities sharing one collection. */
|
|
183
|
-
lastSnapshotRevision: number;
|
|
184
|
-
released: boolean;
|
|
86
|
+
/** A new allocation must receive the complete payload, including after recovery. */
|
|
87
|
+
export function instanceUploadRangesForResident(
|
|
88
|
+
activeIsNew: boolean,
|
|
89
|
+
dirtyRanges: readonly InstanceDirtyRange[],
|
|
90
|
+
fullRange: InstanceDirtyRange,
|
|
91
|
+
): readonly InstanceDirtyRange[] {
|
|
92
|
+
return activeIsNew ? [fullRange] : dirtyRanges;
|
|
185
93
|
}
|
|
186
94
|
|
|
187
|
-
interface
|
|
95
|
+
interface Projection extends InstanceCollectionSnapshot {
|
|
96
|
+
readonly world: World;
|
|
97
|
+
readonly entity: number;
|
|
98
|
+
}
|
|
99
|
+
interface Residency {
|
|
188
100
|
readonly frameNumber: number;
|
|
189
101
|
readonly residentGeneration: number | undefined;
|
|
190
102
|
readonly lane: InstanceSubmissionLane;
|
|
@@ -196,300 +108,120 @@ interface CollectionResidency {
|
|
|
196
108
|
readonly error: InstanceCollectionInspection['error'];
|
|
197
109
|
}
|
|
198
110
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
while (capacity < required) capacity *= 2;
|
|
202
|
-
return capacity;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function invalid(
|
|
206
|
-
operation: InstanceCollectionInvalidDetail['operation'],
|
|
207
|
-
expected: string,
|
|
208
|
-
actual: number | string,
|
|
209
|
-
collectionId?: number,
|
|
210
|
-
context?: {
|
|
211
|
-
readonly requestedBytes?: number;
|
|
212
|
-
readonly supportedBytes?: number;
|
|
213
|
-
readonly cause?: string;
|
|
214
|
-
readonly recovery?: string;
|
|
215
|
-
},
|
|
216
|
-
): InstanceCollectionError {
|
|
217
|
-
const hint = 'repair the collection payload and retry the same authoring operation';
|
|
218
|
-
return new InstanceCollectionError(
|
|
219
|
-
'instance-collection-invalid',
|
|
220
|
-
expected,
|
|
221
|
-
hint,
|
|
222
|
-
{ operation, expected, actual, ...(collectionId === undefined ? {} : { collectionId }) },
|
|
223
|
-
instanceCollectionFailureFacts(
|
|
224
|
-
context?.cause ?? `invalid-${operation}-authoring`,
|
|
225
|
-
context?.recovery ?? hint,
|
|
226
|
-
context?.requestedBytes ?? 0,
|
|
227
|
-
context?.supportedBytes,
|
|
228
|
-
),
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function validateTransforms(
|
|
233
|
-
operation: InstanceCollectionInvalidDetail['operation'],
|
|
234
|
-
transforms: Float32Array,
|
|
235
|
-
collectionId?: number,
|
|
236
|
-
): InstanceCollectionError | undefined {
|
|
237
|
-
if (!(transforms instanceof Float32Array)) {
|
|
238
|
-
return invalid(operation, 'transforms is a Float32Array', typeof transforms, collectionId, {
|
|
239
|
-
cause: 'invalid-transform-type',
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
if (transforms.length % MATRIX_STRIDE !== 0) {
|
|
243
|
-
return invalid(
|
|
244
|
-
operation,
|
|
245
|
-
`transforms.length is a multiple of ${MATRIX_STRIDE}`,
|
|
246
|
-
transforms.length,
|
|
247
|
-
collectionId,
|
|
248
|
-
{
|
|
249
|
-
requestedBytes: transforms.byteLength,
|
|
250
|
-
cause: 'invalid-transform-stride',
|
|
251
|
-
},
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
for (const value of transforms) {
|
|
255
|
-
if (!Number.isFinite(value)) {
|
|
256
|
-
return invalid(operation, 'every transform value is finite', value, collectionId, {
|
|
257
|
-
requestedBytes: transforms.byteLength,
|
|
258
|
-
cause: 'invalid-transform-value',
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
return undefined;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
function appendRange(ranges: InstanceDirtyRange[], start: number, end: number): void {
|
|
266
|
-
if (start >= end) return;
|
|
267
|
-
// Updates are allowed to arrive in any order. Insert at the first range
|
|
268
|
-
// whose end reaches the new interval, then consume every range that starts
|
|
269
|
-
// before the merged end. This preserves the complete union for both
|
|
270
|
-
// adjacent and overlapping writes (for example [10, 12) then [8, 11)).
|
|
271
|
-
let index = 0;
|
|
272
|
-
while (index < ranges.length) {
|
|
273
|
-
const existing = ranges[index];
|
|
274
|
-
if (existing === undefined || existing.end >= start) break;
|
|
275
|
-
index += 1;
|
|
276
|
-
}
|
|
277
|
-
while (index < ranges.length) {
|
|
278
|
-
const existing = ranges[index];
|
|
279
|
-
if (existing === undefined || existing.start > end) break;
|
|
280
|
-
start = Math.min(start, existing.start);
|
|
281
|
-
end = Math.max(end, existing.end);
|
|
282
|
-
ranges.splice(index, 1);
|
|
283
|
-
}
|
|
284
|
-
ranges.splice(index, 0, { start, end });
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function appendDirtyRange(record: CollectionRecord, start: number, end: number): void {
|
|
288
|
-
appendRange(record.dirtyRanges, start, end);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
function missing(
|
|
292
|
-
operation: InstanceCollectionInvalidDetail['operation'],
|
|
293
|
-
id: InstanceCollectionId,
|
|
294
|
-
): InstanceCollectionError {
|
|
295
|
-
return new InstanceCollectionError(
|
|
296
|
-
'instance-collection-not-found',
|
|
297
|
-
`instance collection ${Number(id)} is live and owned by this Renderer`,
|
|
298
|
-
'create a collection with renderer.instances.create or retain the original collection id',
|
|
299
|
-
{ operation, expected: 'a live instance collection id', actual: Number(id), collectionId: id },
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Renderer-owned canonical storage for explicit instance transforms.
|
|
305
|
-
*
|
|
306
|
-
* ECS carries only `Instances.collectionId`; this owner keeps the copied
|
|
307
|
-
* matrices, revision and dirty intervals independent of archetype capacity.
|
|
308
|
-
* Snapshots are detached before they cross into extraction, so callers cannot
|
|
309
|
-
* mutate the canonical source behind the revision protocol.
|
|
310
|
-
*/
|
|
311
|
-
export class InstanceCollectionStore {
|
|
111
|
+
/** Rebuildable renderer projection. All authoring and entity lifetime belong to World. */
|
|
112
|
+
export class InstanceProjectionStore {
|
|
312
113
|
private nextId = 1;
|
|
313
|
-
private
|
|
314
|
-
private
|
|
315
|
-
private
|
|
316
|
-
private readonly
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
transforms: new Float32Array(input.transforms),
|
|
114
|
+
private nextGeneration = 1;
|
|
115
|
+
private identities = new WeakMap<World, Map<number, InstanceCollectionId>>();
|
|
116
|
+
private readonly records = new Map<InstanceCollectionId, Projection>();
|
|
117
|
+
private readonly residency = new Map<InstanceCollectionId, Residency>();
|
|
118
|
+
|
|
119
|
+
project(world: World, entity: number, transforms: ArrayLike<number>): InstanceCollectionSnapshot {
|
|
120
|
+
const collectionId =
|
|
121
|
+
this.identities.get(world)?.get(entity) ?? (this.nextId++ as InstanceCollectionId);
|
|
122
|
+
const previous = this.records.get(collectionId);
|
|
123
|
+
if (
|
|
124
|
+
previous !== undefined &&
|
|
125
|
+
previous.transforms.length === transforms.length &&
|
|
126
|
+
previous.transforms.every((value, index) => Object.is(value, transforms[index]))
|
|
127
|
+
)
|
|
128
|
+
return previous;
|
|
129
|
+
const count = transforms.length / MATRIX_STRIDE;
|
|
130
|
+
// Ordinals are identities within the authored array. Pose edits retain them;
|
|
131
|
+
// resizing seeds topology anew so new instances cannot inherit old motion.
|
|
132
|
+
const generations =
|
|
133
|
+
previous?.count === count
|
|
134
|
+
? previous.generations
|
|
135
|
+
: Uint32Array.from({ length: count }, () => this.nextGeneration++);
|
|
136
|
+
const record: Projection = {
|
|
137
|
+
collectionId,
|
|
138
|
+
world,
|
|
139
|
+
entity,
|
|
140
|
+
transforms: new Float32Array(transforms),
|
|
341
141
|
generations,
|
|
342
142
|
count,
|
|
343
|
-
|
|
344
|
-
revision: 1,
|
|
345
|
-
dirtyRanges: count === 0 ? [] : [{ start: 0, end: count }],
|
|
346
|
-
lastSnapshotRevision: 0,
|
|
347
|
-
released: false,
|
|
143
|
+
revision: (previous?.revision ?? 0) + 1,
|
|
348
144
|
};
|
|
349
|
-
|
|
350
|
-
this.epochValue += 1;
|
|
351
|
-
return ok(this.info(record));
|
|
145
|
+
return record;
|
|
352
146
|
}
|
|
353
147
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
this.epochValue += 1;
|
|
383
|
-
return ok(this.info(record.value));
|
|
148
|
+
/** Called only after the owning RenderScene accepts its prepared changes. */
|
|
149
|
+
accept(
|
|
150
|
+
world: World,
|
|
151
|
+
entity: number,
|
|
152
|
+
snapshot: {
|
|
153
|
+
readonly collectionId?: InstanceCollectionId;
|
|
154
|
+
readonly revision?: number;
|
|
155
|
+
readonly transforms: Float32Array;
|
|
156
|
+
readonly generations?: Uint32Array;
|
|
157
|
+
},
|
|
158
|
+
): void {
|
|
159
|
+
const { collectionId, revision, transforms, generations } = snapshot;
|
|
160
|
+
if (collectionId === undefined || revision === undefined || generations === undefined) return;
|
|
161
|
+
let entities = this.identities.get(world);
|
|
162
|
+
if (entities === undefined) {
|
|
163
|
+
entities = new Map();
|
|
164
|
+
this.identities.set(world, entities);
|
|
165
|
+
}
|
|
166
|
+
entities.set(entity, collectionId);
|
|
167
|
+
this.records.set(collectionId, {
|
|
168
|
+
collectionId,
|
|
169
|
+
revision,
|
|
170
|
+
transforms,
|
|
171
|
+
generations,
|
|
172
|
+
count: transforms.length / MATRIX_STRIDE,
|
|
173
|
+
world,
|
|
174
|
+
entity,
|
|
175
|
+
});
|
|
384
176
|
}
|
|
385
177
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
requestedBytes: input.transforms.byteLength,
|
|
398
|
-
supportedBytes: record.value.capacity * MATRIX_STRIDE * Float32Array.BYTES_PER_ELEMENT,
|
|
399
|
-
cause: 'invalid-update-range-start',
|
|
400
|
-
}),
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
const span = input.transforms.length / MATRIX_STRIDE;
|
|
404
|
-
const attemptedEnd = input.start + span;
|
|
405
|
-
if (attemptedEnd > record.value.count) {
|
|
406
|
-
return err(
|
|
407
|
-
invalid(
|
|
408
|
-
'update',
|
|
409
|
-
`start + matrix count is <= collection count (${record.value.count})`,
|
|
410
|
-
attemptedEnd,
|
|
411
|
-
id,
|
|
412
|
-
{
|
|
413
|
-
requestedBytes: attemptedEnd * MATRIX_STRIDE * Float32Array.BYTES_PER_ELEMENT,
|
|
414
|
-
supportedBytes: record.value.count * MATRIX_STRIDE * Float32Array.BYTES_PER_ELEMENT,
|
|
415
|
-
cause: 'invalid-update-range-end',
|
|
416
|
-
},
|
|
417
|
-
),
|
|
418
|
-
);
|
|
419
|
-
}
|
|
420
|
-
if (record.value.lastSnapshotRevision === record.value.revision) {
|
|
421
|
-
record.value.dirtyRanges = [];
|
|
178
|
+
release(world: World, entity: number): void {
|
|
179
|
+
const entities = this.identities.get(world);
|
|
180
|
+
const id = entities?.get(entity);
|
|
181
|
+
if (id === undefined) return;
|
|
182
|
+
entities?.delete(entity);
|
|
183
|
+
this.records.delete(id);
|
|
184
|
+
this.residency.delete(id);
|
|
185
|
+
}
|
|
186
|
+
retain(ids: ReadonlySet<InstanceCollectionId>): void {
|
|
187
|
+
for (const record of this.records.values()) {
|
|
188
|
+
if (!ids.has(record.collectionId)) this.release(record.world, record.entity);
|
|
422
189
|
}
|
|
423
|
-
record.value.transforms.set(input.transforms, input.start * MATRIX_STRIDE);
|
|
424
|
-
// An update changes a pose while retaining the same ordinal identity.
|
|
425
|
-
// Keep its generation stable so the record stage can pair this current
|
|
426
|
-
// transform with the last submitted transform and expose real velocity.
|
|
427
|
-
// `replace` is the explicit topology boundary that advances generations
|
|
428
|
-
// for compaction, reorder, retirement, and newly occupied ordinals.
|
|
429
|
-
record.value.revision += 1;
|
|
430
|
-
appendDirtyRange(record.value, input.start, input.start + span);
|
|
431
|
-
this.epochValue += 1;
|
|
432
|
-
return ok(this.info(record.value));
|
|
433
190
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
191
|
+
dispose(): void {
|
|
192
|
+
this.records.clear();
|
|
193
|
+
this.residency.clear();
|
|
194
|
+
this.identities = new WeakMap();
|
|
438
195
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
* Return detached residency facts for every live collection.
|
|
442
|
-
*
|
|
443
|
-
* @internal Record-stage evidence is reported through the two methods below;
|
|
444
|
-
* callers only receive immutable PODs and never GPU handles.
|
|
445
|
-
*/
|
|
446
|
-
_inspections(): readonly InstanceCollectionInspection[] {
|
|
447
|
-
return Object.freeze(
|
|
448
|
-
[...this.records.values()].map((record) => this.projectInspection(record)),
|
|
449
|
-
);
|
|
196
|
+
_resetResidency(): void {
|
|
197
|
+
this.residency.clear();
|
|
450
198
|
}
|
|
451
199
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
readonly uploadRanges: readonly InstanceDirtyRange[];
|
|
459
|
-
readonly uploadedBytes: number;
|
|
460
|
-
readonly requestedBytes: number;
|
|
461
|
-
readonly supportedBytes: number | undefined;
|
|
462
|
-
readonly backend: InstanceBackendKind;
|
|
463
|
-
}): void {
|
|
200
|
+
_reportResidency(
|
|
201
|
+
input: Omit<Residency, 'error' | 'lane'> & {
|
|
202
|
+
readonly collectionId: InstanceCollectionId;
|
|
203
|
+
readonly lane: Exclude<InstanceSubmissionLane, 'unresident' | 'unavailable'>;
|
|
204
|
+
},
|
|
205
|
+
): void {
|
|
464
206
|
if (!this.records.has(input.collectionId)) return;
|
|
465
207
|
const previous = this.residency.get(input.collectionId);
|
|
466
|
-
const sameFrame =
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
const uploadRanges =
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
input.uploadRanges.map((range) => ({ ...range })),
|
|
477
|
-
)
|
|
478
|
-
: input.uploadRanges.map((range) => ({ ...range }));
|
|
208
|
+
const sameFrame = previous?.frameNumber === input.frameNumber && previous.error === undefined;
|
|
209
|
+
const ranges = [...(sameFrame ? previous.uploadRanges : []), ...input.uploadRanges]
|
|
210
|
+
.map((range) => ({ ...range }))
|
|
211
|
+
.sort((a, b) => a.start - b.start);
|
|
212
|
+
const uploadRanges: InstanceDirtyRange[] = [];
|
|
213
|
+
for (const range of ranges) {
|
|
214
|
+
const last = uploadRanges.at(-1);
|
|
215
|
+
if (last !== undefined && range.start <= last.end) last.end = Math.max(last.end, range.end);
|
|
216
|
+
else uploadRanges.push(range);
|
|
217
|
+
}
|
|
479
218
|
this.residency.set(input.collectionId, {
|
|
480
|
-
|
|
481
|
-
residentGeneration: input.residentGeneration,
|
|
482
|
-
lane: input.lane,
|
|
219
|
+
...input,
|
|
483
220
|
uploadRanges,
|
|
484
|
-
uploadedBytes: sameFrame ? previous.uploadedBytes
|
|
485
|
-
requestedBytes: input.requestedBytes,
|
|
486
|
-
supportedBytes: input.supportedBytes,
|
|
487
|
-
backend: input.backend,
|
|
221
|
+
uploadedBytes: input.uploadedBytes + (sameFrame ? previous.uploadedBytes : 0),
|
|
488
222
|
error: undefined,
|
|
489
223
|
});
|
|
490
224
|
}
|
|
491
|
-
|
|
492
|
-
/** @internal Renderer record owner reports a typed admission failure. */
|
|
493
225
|
_reportFailure(input: {
|
|
494
226
|
readonly collectionId: InstanceCollectionId;
|
|
495
227
|
readonly code: InstanceCollectionFailureCode;
|
|
@@ -515,176 +247,24 @@ export class InstanceCollectionStore {
|
|
|
515
247
|
},
|
|
516
248
|
});
|
|
517
249
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
// this collection. The next authoring mutation starts a fresh interval
|
|
537
|
-
// set once this revision has been observed.
|
|
538
|
-
return ok(result);
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* Read a detached matrix view without advancing the render-consumption
|
|
543
|
-
* cursor. Inspection and picking may call this between authoring updates;
|
|
544
|
-
* the next renderer snapshot must still receive the complete dirty union.
|
|
545
|
-
*/
|
|
546
|
-
peek(id: InstanceCollectionId): InstanceCollectionResult<InstanceCollectionSnapshot> {
|
|
547
|
-
const record = this.live('inspect', id);
|
|
548
|
-
return record.ok ? ok(this.detachedSnapshot(record.value)) : record;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
release(id: InstanceCollectionId): InstanceCollectionResult<void> {
|
|
552
|
-
const record = this.records.get(id);
|
|
553
|
-
if (record === undefined) return err(missing('release', id));
|
|
554
|
-
if (record.released) {
|
|
555
|
-
return err(
|
|
556
|
-
new InstanceCollectionError(
|
|
557
|
-
'instance-collection-released',
|
|
558
|
-
`instance collection ${Number(id)} has not already been released`,
|
|
559
|
-
'do not reuse a released collection id; create a new collection',
|
|
560
|
-
{
|
|
561
|
-
operation: 'release',
|
|
562
|
-
expected: 'a live instance collection id',
|
|
563
|
-
actual: Number(id),
|
|
564
|
-
collectionId: id,
|
|
565
|
-
},
|
|
566
|
-
),
|
|
567
|
-
);
|
|
568
|
-
}
|
|
569
|
-
record.released = true;
|
|
570
|
-
this.records.delete(id);
|
|
571
|
-
this.residency.delete(id);
|
|
572
|
-
this.epochValue += 1;
|
|
573
|
-
return ok(undefined);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
/** Drop all canonical matrices during Renderer disposal. */
|
|
577
|
-
dispose(): void {
|
|
578
|
-
if (this.disposed) return;
|
|
579
|
-
this.disposed = true;
|
|
580
|
-
for (const record of this.records.values()) record.released = true;
|
|
581
|
-
this.records.clear();
|
|
582
|
-
this.residency.clear();
|
|
583
|
-
this.epochValue += 1;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
private live(
|
|
587
|
-
operation: InstanceCollectionInvalidDetail['operation'],
|
|
588
|
-
id: InstanceCollectionId,
|
|
589
|
-
): InstanceCollectionResult<CollectionRecord> {
|
|
590
|
-
if (!Number.isInteger(id) || id <= 0) {
|
|
591
|
-
return err(invalid(operation, 'collectionId is a positive integer', id, id));
|
|
592
|
-
}
|
|
593
|
-
if (this.disposed) {
|
|
594
|
-
return err(
|
|
595
|
-
new InstanceCollectionError(
|
|
596
|
-
'instance-collection-released',
|
|
597
|
-
'the Renderer-owned instance collection store is live',
|
|
598
|
-
'create a new Renderer before using instance collections',
|
|
599
|
-
{ operation, expected: 'a live collection store', actual: 'disposed', collectionId: id },
|
|
600
|
-
),
|
|
601
|
-
);
|
|
602
|
-
}
|
|
603
|
-
const record = this.records.get(id);
|
|
604
|
-
return record === undefined ? err(missing(operation, id)) : ok(record);
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
private detachedSnapshot(record: CollectionRecord): InstanceCollectionSnapshot {
|
|
608
|
-
return {
|
|
609
|
-
...this.info(record),
|
|
610
|
-
transforms: new Float32Array(record.transforms),
|
|
611
|
-
generations: new Uint32Array(record.generations),
|
|
612
|
-
dirtyRanges: record.dirtyRanges.map((range) => ({ ...range })),
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
private info(record: CollectionRecord): InstanceCollectionInfo {
|
|
617
|
-
return Object.freeze({
|
|
618
|
-
collectionId: record.id,
|
|
619
|
-
count: record.count,
|
|
620
|
-
capacity: record.capacity,
|
|
621
|
-
revision: record.revision,
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
private allocateGenerations(count: number): Uint32Array {
|
|
626
|
-
const generations = new Uint32Array(count);
|
|
627
|
-
for (let index = 0; index < count; index += 1) {
|
|
628
|
-
generations[index] = this.nextInstanceGeneration;
|
|
629
|
-
this.nextInstanceGeneration = (this.nextInstanceGeneration + 1) >>> 0 || 1;
|
|
630
|
-
}
|
|
631
|
-
return generations;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
private validateReplacementGenerations(
|
|
635
|
-
generations: Uint32Array,
|
|
636
|
-
count: number,
|
|
637
|
-
collectionId: InstanceCollectionId,
|
|
638
|
-
): InstanceCollectionResult<Uint32Array> {
|
|
639
|
-
if (!(generations instanceof Uint32Array) || generations.length !== count) {
|
|
640
|
-
return err(
|
|
641
|
-
invalid(
|
|
642
|
-
'replace',
|
|
643
|
-
`generations is a Uint32Array with ${count} entries`,
|
|
644
|
-
generations instanceof Uint32Array ? generations.length : typeof generations,
|
|
645
|
-
collectionId,
|
|
646
|
-
{ requestedBytes: generations?.byteLength ?? 0, cause: 'invalid-generation-shape' },
|
|
647
|
-
),
|
|
648
|
-
);
|
|
649
|
-
}
|
|
650
|
-
const seen = new Set<number>();
|
|
651
|
-
for (const generation of generations) {
|
|
652
|
-
if (generation === 0 || seen.has(generation)) {
|
|
653
|
-
return err(
|
|
654
|
-
invalid(
|
|
655
|
-
'replace',
|
|
656
|
-
'generations contain unique non-zero identity tokens',
|
|
657
|
-
generation,
|
|
658
|
-
collectionId,
|
|
659
|
-
{
|
|
660
|
-
requestedBytes: generations.byteLength,
|
|
661
|
-
cause: 'invalid-generation-identity',
|
|
662
|
-
},
|
|
663
|
-
),
|
|
664
|
-
);
|
|
665
|
-
}
|
|
666
|
-
seen.add(generation);
|
|
667
|
-
if (generation >= this.nextInstanceGeneration) {
|
|
668
|
-
this.nextInstanceGeneration = (generation + 1) >>> 0 || 1;
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
return ok(new Uint32Array(generations));
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
private projectInspection(record: CollectionRecord): InstanceCollectionInspection {
|
|
675
|
-
const residency = this.residency.get(record.id);
|
|
676
|
-
return Object.freeze({
|
|
677
|
-
...this.info(record),
|
|
678
|
-
residentGeneration: residency?.residentGeneration,
|
|
679
|
-
lane: residency?.lane ?? 'unresident',
|
|
680
|
-
dirtyRanges: Object.freeze(record.dirtyRanges.map((range) => ({ ...range }))),
|
|
681
|
-
uploadRanges: Object.freeze(residency?.uploadRanges.map((range) => ({ ...range })) ?? []),
|
|
682
|
-
uploadedBytes: residency?.uploadedBytes ?? 0,
|
|
683
|
-
requestedBytes: residency?.requestedBytes ?? record.count * MATRIX_STRIDE * 4,
|
|
684
|
-
supportedBytes: residency?.supportedBytes,
|
|
685
|
-
backend: residency?.backend ?? 'unknown',
|
|
686
|
-
owner: 'renderer.instances',
|
|
687
|
-
error: residency?.error,
|
|
250
|
+
_inspections(frameNumber: number): readonly InstanceCollectionInspection[] {
|
|
251
|
+
return [...this.records.values()].map((record) => {
|
|
252
|
+
const resident = this.residency.get(record.collectionId);
|
|
253
|
+
const current = resident?.frameNumber === frameNumber;
|
|
254
|
+
return {
|
|
255
|
+
collectionId: record.collectionId,
|
|
256
|
+
count: record.count,
|
|
257
|
+
revision: record.revision,
|
|
258
|
+
residentGeneration: resident?.residentGeneration,
|
|
259
|
+
lane: resident?.lane ?? 'unresident',
|
|
260
|
+
uploadRanges: current ? resident.uploadRanges.map((range) => ({ ...range })) : [],
|
|
261
|
+
uploadedBytes: current ? resident.uploadedBytes : 0,
|
|
262
|
+
requestedBytes: resident?.requestedBytes ?? record.transforms.byteLength,
|
|
263
|
+
supportedBytes: resident?.supportedBytes,
|
|
264
|
+
backend: resident?.backend ?? 'unknown',
|
|
265
|
+
owner: 'renderer.instances',
|
|
266
|
+
error: resident?.error,
|
|
267
|
+
};
|
|
688
268
|
});
|
|
689
269
|
}
|
|
690
270
|
}
|