@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
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import { RuntimeMaterialValue, RuntimeMeshVertices } from '@forgeax/engine-assets-runtime';
|
|
1
2
|
import type { EntityHandle, Query, World } from '@forgeax/engine-ecs';
|
|
2
|
-
import {
|
|
3
|
-
|
|
3
|
+
import {
|
|
4
|
+
createStateProjection,
|
|
5
|
+
type RenderReadLease,
|
|
6
|
+
type RenderReadVersion,
|
|
7
|
+
type StateProjection,
|
|
8
|
+
type StateProjectionBatch,
|
|
9
|
+
} from '@forgeax/engine-ecs/projection';
|
|
4
10
|
import { box3, frustum, mat4 } from '@forgeax/engine-math';
|
|
5
11
|
import { type RhiDevice, RhiError } from '@forgeax/engine-rhi';
|
|
6
|
-
import {
|
|
7
|
-
ChildOf,
|
|
8
|
-
collectSubtree,
|
|
9
|
-
GlobalTransform,
|
|
10
|
-
MorphWeights,
|
|
11
|
-
Transform,
|
|
12
|
-
} from '@forgeax/engine-scene';
|
|
12
|
+
import { ChildOf, Children, GlobalTransform, MorphWeights, Transform } from '@forgeax/engine-scene';
|
|
13
13
|
import { Skin } from '@forgeax/engine-skinning';
|
|
14
14
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
15
15
|
import {
|
|
@@ -37,7 +37,7 @@ import type {
|
|
|
37
37
|
GpuDrivenStructureMetrics,
|
|
38
38
|
PersistentRenderSceneInspection,
|
|
39
39
|
} from '../inspection-types';
|
|
40
|
-
import type {
|
|
40
|
+
import type { InstanceProjectionStore } from '../instances';
|
|
41
41
|
import { fingerprintNumericArray, InstanceBoundsCache } from '../instances-derived-bounds';
|
|
42
42
|
import type { PointsLinesInspection } from '../points-lines/inspection';
|
|
43
43
|
import type { PointsLinesRetainedSnapshot } from '../points-lines/snapshot';
|
|
@@ -62,7 +62,11 @@ import {
|
|
|
62
62
|
type TransmissionDemand,
|
|
63
63
|
type TransmissionDemandOperation,
|
|
64
64
|
} from '../transmission/projection';
|
|
65
|
-
import {
|
|
65
|
+
import {
|
|
66
|
+
type ProbeBlendBufferProjection,
|
|
67
|
+
ProbeBlendSceneProjection,
|
|
68
|
+
type ProbeSceneObjectInput,
|
|
69
|
+
} from './probe-blend';
|
|
66
70
|
import type {
|
|
67
71
|
RenderSceneApplyResult,
|
|
68
72
|
RenderSceneBounds,
|
|
@@ -402,16 +406,33 @@ export class RenderScene {
|
|
|
402
406
|
return this.emptyResult();
|
|
403
407
|
}
|
|
404
408
|
|
|
405
|
-
|
|
409
|
+
// Prepare every potentially fallible payload copy before mutating retained
|
|
410
|
+
// columns. The commit loop below only uses owned POD and borrowed numeric spans.
|
|
411
|
+
const preparedOperations = operations.map((operation): RenderSceneOperation => {
|
|
412
|
+
if (operation.kind === 'remove') return operation;
|
|
406
413
|
if (
|
|
407
|
-
operation.kind === 'update' &&
|
|
408
414
|
operation.snapshot !== undefined &&
|
|
409
415
|
(operation.worldId !== operation.snapshot.worldId ||
|
|
410
416
|
operation.entityKey !== operation.snapshot.entityKey)
|
|
411
417
|
) {
|
|
412
418
|
throw new RangeError('RenderScene update identity must match its source snapshot');
|
|
413
419
|
}
|
|
414
|
-
|
|
420
|
+
return {
|
|
421
|
+
...operation,
|
|
422
|
+
...(operation.snapshot === undefined ? {} : { snapshot: ownSnapshot(operation.snapshot) }),
|
|
423
|
+
...(operation.instances === undefined
|
|
424
|
+
? {}
|
|
425
|
+
: {
|
|
426
|
+
instances: {
|
|
427
|
+
...operation.instances,
|
|
428
|
+
transforms: new Float32Array(operation.instances.transforms),
|
|
429
|
+
...(operation.instances.generations === undefined
|
|
430
|
+
? {}
|
|
431
|
+
: { generations: new Uint32Array(operation.instances.generations) }),
|
|
432
|
+
},
|
|
433
|
+
}),
|
|
434
|
+
};
|
|
435
|
+
});
|
|
415
436
|
this.deltaFrames += 1;
|
|
416
437
|
this.renderableScans = operations.length;
|
|
417
438
|
const pendingByWorld = new Map<number, Map<number, PendingIdentity>>();
|
|
@@ -453,7 +474,7 @@ export class RenderScene {
|
|
|
453
474
|
}
|
|
454
475
|
}
|
|
455
476
|
};
|
|
456
|
-
for (const operation of
|
|
477
|
+
for (const operation of preparedOperations) {
|
|
457
478
|
const pending = pendingFor(operation.worldId, operation.entityKey);
|
|
458
479
|
if (operation.kind === 'remove') {
|
|
459
480
|
pending.current = undefined;
|
|
@@ -462,7 +483,7 @@ export class RenderScene {
|
|
|
462
483
|
}
|
|
463
484
|
if (operation.snapshot !== undefined) {
|
|
464
485
|
const previousMaterials = pending.current?.materials;
|
|
465
|
-
const next =
|
|
486
|
+
const next = operation.snapshot;
|
|
466
487
|
pending.current =
|
|
467
488
|
previousMaterials !== undefined &&
|
|
468
489
|
previousMaterials.length === next.materials.length &&
|
|
@@ -478,13 +499,7 @@ export class RenderScene {
|
|
|
478
499
|
if (operation.instances !== undefined) {
|
|
479
500
|
pending.current = {
|
|
480
501
|
...pending.current,
|
|
481
|
-
instances:
|
|
482
|
-
...operation.instances,
|
|
483
|
-
transforms: new Float32Array(operation.instances.transforms),
|
|
484
|
-
...(operation.instances.generations === undefined
|
|
485
|
-
? {}
|
|
486
|
-
: { generations: new Uint32Array(operation.instances.generations) }),
|
|
487
|
-
},
|
|
502
|
+
instances: operation.instances,
|
|
488
503
|
};
|
|
489
504
|
pending.instanceChanged = true;
|
|
490
505
|
}
|
|
@@ -753,6 +768,11 @@ export class RenderScene {
|
|
|
753
768
|
return this.slotSnapshot;
|
|
754
769
|
}
|
|
755
770
|
|
|
771
|
+
/** Cheap owner revision for retained derived projections. */
|
|
772
|
+
revisionValue(): number {
|
|
773
|
+
return this.revision;
|
|
774
|
+
}
|
|
775
|
+
|
|
756
776
|
slot(worldId: number, entityKey: number): RenderSceneSlot | undefined {
|
|
757
777
|
return this.lookup(worldId, entityKey);
|
|
758
778
|
}
|
|
@@ -1047,10 +1067,10 @@ export class RenderScene {
|
|
|
1047
1067
|
export interface PersistentRenderSceneOptions {
|
|
1048
1068
|
readonly getDevice?: (() => RhiDevice) | undefined;
|
|
1049
1069
|
readonly onGpuError?: ((error: RhiError) => void) | undefined;
|
|
1050
|
-
readonly
|
|
1070
|
+
readonly onRuntimeAssetChange?: ((worldId: number, handle: number) => void) | undefined;
|
|
1051
1071
|
readonly configuredQueryBudget?: number | undefined;
|
|
1052
|
-
/**
|
|
1053
|
-
readonly instanceCollections?:
|
|
1072
|
+
/** Instance projection accepted by the same World source update flow. */
|
|
1073
|
+
readonly instanceCollections?: InstanceProjectionStore | undefined;
|
|
1054
1074
|
}
|
|
1055
1075
|
|
|
1056
1076
|
export interface PersistentGpuDrivenState {
|
|
@@ -1059,7 +1079,11 @@ export interface PersistentGpuDrivenState {
|
|
|
1059
1079
|
readonly slots: readonly RenderSceneSlot[];
|
|
1060
1080
|
/** Stable renderer-local World keys aligned with RenderSceneSlot.worldId. */
|
|
1061
1081
|
readonly worldKeys?: readonly number[];
|
|
1082
|
+
/** Public World identities aligned with RenderSceneSlot.worldId. */
|
|
1083
|
+
readonly worldIdentities?: readonly string[];
|
|
1062
1084
|
readonly structureMetrics?: GpuDrivenStructureMetrics;
|
|
1085
|
+
/** Stable retained ProbeBlend upload projection from the Scene owner. */
|
|
1086
|
+
readonly probeBlend?: ProbeBlendBufferProjection;
|
|
1063
1087
|
}
|
|
1064
1088
|
|
|
1065
1089
|
export interface CpuDirectViewInput {
|
|
@@ -1137,7 +1161,11 @@ interface PersistentCompositionEntry {
|
|
|
1137
1161
|
readonly readVersions: RenderReadVersion[];
|
|
1138
1162
|
readonly leaseIdentities: readonly string[];
|
|
1139
1163
|
readonly transformQueries: readonly GlobalTransformChangeQuery[];
|
|
1140
|
-
readonly
|
|
1164
|
+
readonly sourceStates: readonly {
|
|
1165
|
+
projection: StateProjection;
|
|
1166
|
+
entities: Map<number, EntityHandle>;
|
|
1167
|
+
contentHandles: Map<number, readonly number[]>;
|
|
1168
|
+
}[];
|
|
1141
1169
|
readonly dispatchBySlot: Map<number, readonly DispatchEntry[]>;
|
|
1142
1170
|
dispatchRevision: number;
|
|
1143
1171
|
dispatchCache: { readonly revision: number; readonly value: DispatchEntry[] } | undefined;
|
|
@@ -1147,8 +1175,14 @@ interface PersistentCompositionEntry {
|
|
|
1147
1175
|
/** Slots retained for recovery but excluded from direct and indirect submission. */
|
|
1148
1176
|
readonly unavailableSlots: Set<number>;
|
|
1149
1177
|
catalogEpoch: number;
|
|
1150
|
-
instanceEpoch: number;
|
|
1151
1178
|
readonly probeProjection: ProbeBlendSceneProjection;
|
|
1179
|
+
probeObjects:
|
|
1180
|
+
| {
|
|
1181
|
+
readonly revision: number;
|
|
1182
|
+
readonly value: readonly ProbeSceneObjectInput[];
|
|
1183
|
+
readonly surfaceValue: readonly ProbeSceneObjectInput[];
|
|
1184
|
+
}
|
|
1185
|
+
| undefined;
|
|
1152
1186
|
temporalDemanded: boolean;
|
|
1153
1187
|
gpuDrivenSceneRequired: boolean;
|
|
1154
1188
|
}
|
|
@@ -1157,7 +1191,6 @@ interface PersistentCompositionEntry {
|
|
|
1157
1191
|
// environment facts are freshly extracted by deriveFramePlan on every draw;
|
|
1158
1192
|
// their edits must not recreate unrelated geometry or its submission history.
|
|
1159
1193
|
const RENDERABLE_SOURCE_COMPONENTS = [
|
|
1160
|
-
GlobalTransform,
|
|
1161
1194
|
ChildOf,
|
|
1162
1195
|
MeshFilter,
|
|
1163
1196
|
MeshRenderer,
|
|
@@ -1172,21 +1205,6 @@ const RENDERABLE_SOURCE_COMPONENTS = [
|
|
|
1172
1205
|
Lines,
|
|
1173
1206
|
SortKey,
|
|
1174
1207
|
] as const;
|
|
1175
|
-
const RENDERABLE_SOURCE_COMPONENT_IDS = new Set(
|
|
1176
|
-
RENDERABLE_SOURCE_COMPONENTS.map((component) => componentId(component)),
|
|
1177
|
-
);
|
|
1178
|
-
const VISIBILITY_DEPENDENCY_COMPONENT_IDS = new Set([
|
|
1179
|
-
componentId(ChildOf),
|
|
1180
|
-
componentId(Visibility),
|
|
1181
|
-
]);
|
|
1182
|
-
const STRUCTURAL_MEMBERSHIP_SCAN_COMPONENT_IDS = new Set([
|
|
1183
|
-
componentId(ChildOf),
|
|
1184
|
-
componentId(Layer),
|
|
1185
|
-
componentId(Visibility),
|
|
1186
|
-
componentId(SpriteRegionOverride),
|
|
1187
|
-
componentId(SortKey),
|
|
1188
|
-
]);
|
|
1189
|
-
|
|
1190
1208
|
function createGlobalTransformChangeQuery(world: World): GlobalTransformChangeQuery {
|
|
1191
1209
|
const result = world.query({ read: [GlobalTransform], changed: [GlobalTransform] });
|
|
1192
1210
|
if (!result.ok) throw result.error;
|
|
@@ -1197,29 +1215,43 @@ function createGlobalTransformChangeQuery(world: World): GlobalTransformChangeQu
|
|
|
1197
1215
|
return query;
|
|
1198
1216
|
}
|
|
1199
1217
|
|
|
1200
|
-
function
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1218
|
+
function createRenderSourceState(world: World) {
|
|
1219
|
+
// Numerical poses already have one span reader. Keep their table membership
|
|
1220
|
+
// in this projection, without scanning their changed rows a second time.
|
|
1221
|
+
const components = [...RENDERABLE_SOURCE_COMPONENTS, RuntimeMaterialValue, RuntimeMeshVertices];
|
|
1222
|
+
const projection = createStateProjection(world, components, [
|
|
1223
|
+
...components,
|
|
1224
|
+
Transform,
|
|
1225
|
+
GlobalTransform,
|
|
1226
|
+
]);
|
|
1227
|
+
const entities = new Map<number, EntityHandle>();
|
|
1228
|
+
const contentHandles = new Map<number, readonly number[]>();
|
|
1229
|
+
const batch = projection.read();
|
|
1230
|
+
for (const index of batch.indices) {
|
|
1231
|
+
const entity = projection.entity(index);
|
|
1232
|
+
if (entity !== undefined) {
|
|
1233
|
+
entities.set(index, entity);
|
|
1234
|
+
const handles: number[] = [];
|
|
1235
|
+
const material = world.hasComponent(entity, RuntimeMaterialValue)
|
|
1236
|
+
? world.get(entity, RuntimeMaterialValue)
|
|
1237
|
+
: undefined;
|
|
1238
|
+
const mesh = world.hasComponent(entity, RuntimeMeshVertices)
|
|
1239
|
+
? world.get(entity, RuntimeMeshVertices)
|
|
1240
|
+
: undefined;
|
|
1241
|
+
if (material?.ok) handles.push(Number(material.value.asset));
|
|
1242
|
+
if (mesh?.ok) handles.push(Number(mesh.value.asset));
|
|
1243
|
+
if (handles.length > 0) contentHandles.set(index, handles);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
return { projection, entities, contentHandles, batch };
|
|
1216
1247
|
}
|
|
1217
1248
|
|
|
1218
|
-
function
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1249
|
+
function isRenderableMember(world: World, entity: number): boolean {
|
|
1250
|
+
return (
|
|
1251
|
+
world.hasComponent(entity as EntityHandle, MeshRenderer) &&
|
|
1252
|
+
world.hasComponent(entity as EntityHandle, Transform) &&
|
|
1253
|
+
world.hasComponent(entity as EntityHandle, MeshFilter)
|
|
1254
|
+
);
|
|
1223
1255
|
}
|
|
1224
1256
|
|
|
1225
1257
|
function sourceMembershipChanged(world: World, slot: RenderSceneSlot): boolean {
|
|
@@ -1899,7 +1931,6 @@ export class PersistentRenderScene {
|
|
|
1899
1931
|
preserveVisibilityOnReorder,
|
|
1900
1932
|
);
|
|
1901
1933
|
}
|
|
1902
|
-
let requiresSourceRefresh = false;
|
|
1903
1934
|
const changedEntitiesByWorld = worlds.map(
|
|
1904
1935
|
(_, worldId) => new Set(entry.pendingRenderableEntitiesByWorld[worldId] ?? []),
|
|
1905
1936
|
);
|
|
@@ -1912,171 +1943,144 @@ export class PersistentRenderScene {
|
|
|
1912
1943
|
contentChangedByWorld[slot.worldId]?.add(slot.entityKey);
|
|
1913
1944
|
}
|
|
1914
1945
|
}
|
|
1915
|
-
const instanceEpoch = this.options.instanceCollections?.epoch ?? 0;
|
|
1916
|
-
if (entry.instanceEpoch !== instanceEpoch) {
|
|
1917
|
-
for (const slot of entry.projection.slotsSnapshot()) {
|
|
1918
|
-
const id = slot.snapshot.instances?.collectionId;
|
|
1919
|
-
if (id === undefined) continue;
|
|
1920
|
-
const current = this.options.instanceCollections?.inspect(id);
|
|
1921
|
-
if (!current?.ok || current.value.revision !== slot.snapshot.instances?.revision) {
|
|
1922
|
-
changedEntitiesByWorld[slot.worldId]?.add(slot.entityKey);
|
|
1923
|
-
}
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
1946
|
const nextReadVersions = entry.readVersions.slice();
|
|
1927
|
-
const
|
|
1928
|
-
const structuralComponentIdsByWorld = worlds.map(() => new Set<number>());
|
|
1929
|
-
let currentRenderableEntitiesByWorld: readonly (ReadonlySet<number> | undefined)[] | undefined;
|
|
1947
|
+
const sourceBatches: StateProjectionBatch[] = [];
|
|
1930
1948
|
const removedSlots: RenderSceneSlot[] = [];
|
|
1931
|
-
|
|
1949
|
+
const transformSpans: WorldTransformSpan[] = [];
|
|
1950
|
+
for (let worldId = 0; worldId < worlds.length; worldId++) {
|
|
1932
1951
|
const world = worlds[worldId];
|
|
1933
|
-
|
|
1934
|
-
const lease = leases
|
|
1935
|
-
if (lease === undefined || entry.leaseIdentities[worldId] !== lease.worldIdentity) {
|
|
1936
|
-
requiresSourceRefresh = true;
|
|
1937
|
-
break;
|
|
1938
|
-
}
|
|
1952
|
+
const source = entry.sourceStates[worldId];
|
|
1953
|
+
const lease = leases[worldId];
|
|
1939
1954
|
const version = entry.readVersions[worldId];
|
|
1940
|
-
if (
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
if (
|
|
1952
|
-
|
|
1955
|
+
if (
|
|
1956
|
+
world === undefined ||
|
|
1957
|
+
source === undefined ||
|
|
1958
|
+
lease === undefined ||
|
|
1959
|
+
version === undefined
|
|
1960
|
+
)
|
|
1961
|
+
continue;
|
|
1962
|
+
const read = lease.readChanges(version);
|
|
1963
|
+
nextReadVersions[worldId] = read.version;
|
|
1964
|
+
const changed = changedEntitiesByWorld[worldId];
|
|
1965
|
+
const content = contentChangedByWorld[worldId];
|
|
1966
|
+
if (changed === undefined || content === undefined) continue;
|
|
1967
|
+
if (version.structureEpoch !== read.version.structureEpoch) {
|
|
1968
|
+
this.visibilityFacets.clear();
|
|
1969
|
+
this.invalidateActiveEntityRevision();
|
|
1953
1970
|
}
|
|
1954
|
-
const
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1971
|
+
const batch = source.projection.read();
|
|
1972
|
+
sourceBatches.push(batch);
|
|
1973
|
+
this.worldEntitiesScanned += batch.scannedRows;
|
|
1974
|
+
const dependencyVisited = new Set<number>();
|
|
1975
|
+
const runtimeAssets = new Set<number>();
|
|
1976
|
+
const runtimeContentChanged =
|
|
1977
|
+
batch.membershipChanged ||
|
|
1978
|
+
batch.changedComponents.includes(RuntimeMaterialValue) ||
|
|
1979
|
+
batch.changedComponents.includes(RuntimeMeshVertices);
|
|
1980
|
+
const contentComponents = RENDERABLE_SOURCE_COMPONENTS.filter(
|
|
1981
|
+
(component) => component !== Instances && batch.changedComponents.includes(component),
|
|
1982
|
+
);
|
|
1983
|
+
const instancesChanged = batch.changedComponents.includes(Instances);
|
|
1984
|
+
const reconcileIdentities =
|
|
1985
|
+
batch.membershipChanged ||
|
|
1986
|
+
runtimeContentChanged ||
|
|
1987
|
+
contentComponents.length > 0 ||
|
|
1988
|
+
instancesChanged;
|
|
1989
|
+
for (const index of reconcileIdentities ? batch.indices : []) {
|
|
1990
|
+
const previous = source.entities.get(index);
|
|
1991
|
+
const current = source.projection.entity(index);
|
|
1992
|
+
if (runtimeContentChanged) {
|
|
1993
|
+
const runtimeHandles = new Set(source.contentHandles.get(index));
|
|
1994
|
+
if (current !== undefined) {
|
|
1995
|
+
const material = world.hasComponent(current, RuntimeMaterialValue)
|
|
1996
|
+
? world.get(current, RuntimeMaterialValue)
|
|
1997
|
+
: undefined;
|
|
1998
|
+
const mesh = world.hasComponent(current, RuntimeMeshVertices)
|
|
1999
|
+
? world.get(current, RuntimeMeshVertices)
|
|
2000
|
+
: undefined;
|
|
2001
|
+
if (material?.ok) runtimeHandles.add(Number(material.value.asset));
|
|
2002
|
+
if (mesh?.ok) runtimeHandles.add(Number(mesh.value.asset));
|
|
1964
2003
|
}
|
|
2004
|
+
for (const handle of runtimeHandles) runtimeAssets.add(handle);
|
|
1965
2005
|
}
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
const query = entry.renderChangeQueries[worldId]?.get(changedComponentId);
|
|
1976
|
-
if (query !== undefined) {
|
|
1977
|
-
for (const row of query) {
|
|
1978
|
-
const entity = row.entity as number;
|
|
1979
|
-
if (VISIBILITY_DEPENDENCY_COMPONENT_IDS.has(changedComponentId)) {
|
|
1980
|
-
const affected = collectSubtree(world, row.entity);
|
|
1981
|
-
for (const dependent of affected) {
|
|
1982
|
-
if (
|
|
1983
|
-
!entry.projection.has(worldId, dependent) &&
|
|
1984
|
-
!world.hasComponent(dependent as EntityHandle, MeshRenderer)
|
|
1985
|
-
)
|
|
1986
|
-
continue;
|
|
1987
|
-
changed.add(dependent);
|
|
1988
|
-
otherChanged?.add(dependent);
|
|
1989
|
-
}
|
|
1990
|
-
} else {
|
|
1991
|
-
changed.add(entity);
|
|
1992
|
-
if (changedComponentId !== componentId(Instances)) otherChanged?.add(entity);
|
|
1993
|
-
}
|
|
2006
|
+
if (previous !== undefined) {
|
|
2007
|
+
const slot = entry.projection.slot(worldId, previous);
|
|
2008
|
+
if (
|
|
2009
|
+
batch.membershipChanged &&
|
|
2010
|
+
slot !== undefined &&
|
|
2011
|
+
(current !== previous || !isRenderableMember(world, previous))
|
|
2012
|
+
) {
|
|
2013
|
+
removedSlots.push(slot);
|
|
2014
|
+
changed.add(previous);
|
|
1994
2015
|
}
|
|
1995
|
-
|
|
1996
|
-
}
|
|
1997
|
-
if (requiresSourceRefresh) break;
|
|
1998
|
-
nextReadVersions[worldId] = read.version;
|
|
1999
|
-
}
|
|
2000
|
-
if (requiresSourceRefresh) {
|
|
2001
|
-
return this.reconcileComposition(worlds, owner, catalogEpoch, buildCandidateFrame, leases);
|
|
2002
|
-
}
|
|
2003
|
-
|
|
2004
|
-
const transformSpans: WorldTransformSpan[] = [];
|
|
2005
|
-
for (let worldId = 0; worldId < entry.transformQueries.length; worldId += 1) {
|
|
2006
|
-
const query = entry.transformQueries[worldId];
|
|
2007
|
-
if (query === undefined) continue;
|
|
2008
|
-
for (const span of query.spans().unwrap()) {
|
|
2009
|
-
const changedWorlds = span.get(GlobalTransform).world;
|
|
2010
|
-
if (!(changedWorlds instanceof Float32Array)) {
|
|
2011
|
-
requiresSourceRefresh = true;
|
|
2012
|
-
break;
|
|
2013
|
-
}
|
|
2014
|
-
transformSpans.push({ worldId, entities: span.entities, worlds: changedWorlds });
|
|
2015
|
-
for (const entity of span.entities) {
|
|
2016
|
-
for (const consumer of entry.skinConsumersByJoint.get(skinJointKey(worldId, entity)) ??
|
|
2016
|
+
for (const consumer of entry.skinConsumersByJoint.get(skinJointKey(worldId, previous)) ??
|
|
2017
2017
|
[]) {
|
|
2018
|
-
|
|
2019
|
-
|
|
2018
|
+
changed.add(consumer);
|
|
2019
|
+
content.add(consumer);
|
|
2020
2020
|
}
|
|
2021
2021
|
}
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
if (
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2022
|
+
if (current === undefined) continue;
|
|
2023
|
+
const existing = entry.projection.slot(worldId, current);
|
|
2024
|
+
const membershipChanged =
|
|
2025
|
+
batch.membershipChanged &&
|
|
2026
|
+
(existing === undefined || sourceMembershipChanged(world, existing));
|
|
2027
|
+
let contentChanged = membershipChanged;
|
|
2028
|
+
for (const component of contentComponents) {
|
|
2029
|
+
if (source.projection.changed(current, component)) contentChanged = true;
|
|
2030
|
+
}
|
|
2031
|
+
if (
|
|
2032
|
+
(contentChanged || (instancesChanged && source.projection.changed(current, Instances))) &&
|
|
2033
|
+
isRenderableMember(world, current)
|
|
2034
|
+
) {
|
|
2035
|
+
changed.add(current);
|
|
2036
|
+
if (contentChanged) content.add(current);
|
|
2037
|
+
}
|
|
2038
|
+
if (
|
|
2039
|
+
version.structureEpoch !== read.version.structureEpoch ||
|
|
2040
|
+
source.projection.changed(current, ChildOf) ||
|
|
2041
|
+
source.projection.changed(current, Visibility)
|
|
2042
|
+
) {
|
|
2043
|
+
if (!dependencyVisited.has(current)) {
|
|
2044
|
+
const pending = [current];
|
|
2045
|
+
while (pending.length > 0) {
|
|
2046
|
+
const dependent = pending.pop();
|
|
2047
|
+
if (dependent === undefined || dependencyVisited.has(dependent)) continue;
|
|
2048
|
+
dependencyVisited.add(dependent);
|
|
2049
|
+
const children = world.hasComponent(dependent, Children)
|
|
2050
|
+
? world.get(dependent, Children)
|
|
2051
|
+
: undefined;
|
|
2052
|
+
if (children?.ok)
|
|
2053
|
+
for (const child of children.value.entities) pending.push(child as EntityHandle);
|
|
2054
|
+
if (!isRenderableMember(world, dependent)) continue;
|
|
2055
|
+
changed.add(dependent);
|
|
2056
|
+
content.add(dependent);
|
|
2054
2057
|
}
|
|
2055
2058
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
for (const handle of runtimeAssets) {
|
|
2062
|
+
this.options.onRuntimeAssetChange?.(worldId, handle);
|
|
2063
|
+
entry.projection.addSharedRefConsumers(worldId, handle, content);
|
|
2064
|
+
}
|
|
2065
|
+
for (const entity of content) changed.add(entity);
|
|
2066
|
+
const query = entry.transformQueries[worldId];
|
|
2067
|
+
if (query !== undefined) {
|
|
2068
|
+
for (const span of query.spans().unwrap()) {
|
|
2069
|
+
const matrices = span.get(GlobalTransform).world;
|
|
2070
|
+
if (!(matrices instanceof Float32Array))
|
|
2071
|
+
throw new Error('GlobalTransform projection must expose a numeric column.');
|
|
2072
|
+
transformSpans.push({ worldId, entities: span.entities, worlds: matrices });
|
|
2073
|
+
if (entry.skinConsumersByJoint.size > 0) {
|
|
2074
|
+
for (const entity of span.entities) {
|
|
2075
|
+
for (const consumer of entry.skinConsumersByJoint.get(
|
|
2076
|
+
skinJointKey(worldId, entity),
|
|
2077
|
+
) ?? []) {
|
|
2078
|
+
changed.add(consumer);
|
|
2079
|
+
content.add(consumer);
|
|
2080
|
+
}
|
|
2071
2081
|
}
|
|
2072
2082
|
}
|
|
2073
2083
|
}
|
|
2074
|
-
for (const slot of entry.projection.slotsSnapshot()) {
|
|
2075
|
-
if (slot.worldId !== worldId || current.has(slot.entityKey)) continue;
|
|
2076
|
-
removedSlots.push(slot);
|
|
2077
|
-
changedEntitiesByWorld[worldId]?.add(slot.entityKey);
|
|
2078
|
-
}
|
|
2079
|
-
this.worldEntitiesScanned += current.size;
|
|
2080
2084
|
}
|
|
2081
2085
|
}
|
|
2082
2086
|
|
|
@@ -2089,6 +2093,8 @@ export class PersistentRenderScene {
|
|
|
2089
2093
|
for (const entityKey of changedEntitiesByWorld[worldId] ?? []) pending.add(entityKey);
|
|
2090
2094
|
}
|
|
2091
2095
|
|
|
2096
|
+
const resourceFrame = buildCandidateFrame('none');
|
|
2097
|
+
for (const batch of sourceBatches) batch.validate();
|
|
2092
2098
|
let changedDelta: RenderSceneApplyResult | undefined;
|
|
2093
2099
|
const hasChangedEntities = changedEntitiesByWorld.some((entities) => entities.size > 0);
|
|
2094
2100
|
if (hasChangedEntities || removedSlots.length > 0 || transformSpans.length > 0) {
|
|
@@ -2103,9 +2109,6 @@ export class PersistentRenderScene {
|
|
|
2103
2109
|
}
|
|
2104
2110
|
for (const slot of removedSlots) {
|
|
2105
2111
|
operations.push({ kind: 'remove', worldId: slot.worldId, entityKey: slot.entityKey });
|
|
2106
|
-
if (slot.snapshot.skinJointEntities !== undefined) {
|
|
2107
|
-
removeSkinConsumer(entry.skinConsumersByJoint, slot.snapshot);
|
|
2108
|
-
}
|
|
2109
2112
|
for (
|
|
2110
2113
|
let materialIndex = 0;
|
|
2111
2114
|
materialIndex < slot.snapshot.materials.length;
|
|
@@ -2162,7 +2165,23 @@ export class PersistentRenderScene {
|
|
|
2162
2165
|
});
|
|
2163
2166
|
publishedEntitiesByWorld[snapshot.worldId]?.add(snapshot.entityKey);
|
|
2164
2167
|
}
|
|
2168
|
+
for (const batch of sourceBatches) batch.validate();
|
|
2165
2169
|
changedDelta = entry.projection.apply(operations, transformSpans);
|
|
2170
|
+
for (const slot of changedDelta.removedSlots) {
|
|
2171
|
+
const world = worlds[slot.worldId];
|
|
2172
|
+
if (world !== undefined) this.options.instanceCollections?.release(world, slot.entityKey);
|
|
2173
|
+
}
|
|
2174
|
+
for (const snapshot of partial?.renderables ?? []) {
|
|
2175
|
+
const world = worlds[snapshot.worldId];
|
|
2176
|
+
if (world === undefined) continue;
|
|
2177
|
+
if (snapshot.instances === undefined)
|
|
2178
|
+
this.options.instanceCollections?.release(world, snapshot.entityKey);
|
|
2179
|
+
else
|
|
2180
|
+
this.options.instanceCollections?.accept(world, snapshot.entityKey, snapshot.instances);
|
|
2181
|
+
}
|
|
2182
|
+
for (const slot of removedSlots)
|
|
2183
|
+
if (slot.snapshot.skinJointEntities !== undefined)
|
|
2184
|
+
removeSkinConsumer(entry.skinConsumersByJoint, slot.snapshot);
|
|
2166
2185
|
const publishedSkinKeys = new Set<string>();
|
|
2167
2186
|
for (const snapshot of partial?.renderables ?? []) {
|
|
2168
2187
|
publishedSkinKeys.add(`${snapshot.worldId}:${snapshot.entityKey}`);
|
|
@@ -2198,7 +2217,7 @@ export class PersistentRenderScene {
|
|
|
2198
2217
|
return (
|
|
2199
2218
|
worldId !== undefined &&
|
|
2200
2219
|
!changedEntitiesByWorld[worldId]?.has(report.entity) &&
|
|
2201
|
-
|
|
2220
|
+
isRenderableMember(report.world, report.entity)
|
|
2202
2221
|
);
|
|
2203
2222
|
}),
|
|
2204
2223
|
...(partial?.hiddenEntityReports ?? []),
|
|
@@ -2227,8 +2246,9 @@ export class PersistentRenderScene {
|
|
|
2227
2246
|
continue;
|
|
2228
2247
|
}
|
|
2229
2248
|
if (slot === undefined) {
|
|
2230
|
-
const
|
|
2231
|
-
if (
|
|
2249
|
+
const world = worlds[worldId];
|
|
2250
|
+
if (world !== undefined && !isRenderableMember(world, entityKey))
|
|
2251
|
+
pending?.delete(entityKey);
|
|
2232
2252
|
continue;
|
|
2233
2253
|
}
|
|
2234
2254
|
// The producer did not publish this requested identity. Keep the
|
|
@@ -2279,9 +2299,43 @@ export class PersistentRenderScene {
|
|
|
2279
2299
|
this.noChangeFrames += 1;
|
|
2280
2300
|
this.syncGpuOwner(entry.token, entry.projection);
|
|
2281
2301
|
}
|
|
2282
|
-
const result = this.deriveFramePlan(entry,
|
|
2302
|
+
const result = this.deriveFramePlan(entry, resourceFrame);
|
|
2303
|
+
for (let worldId = 0; worldId < sourceBatches.length; worldId++) {
|
|
2304
|
+
const batch = sourceBatches[worldId];
|
|
2305
|
+
const source = entry.sourceStates[worldId];
|
|
2306
|
+
if (batch === undefined || source === undefined) continue;
|
|
2307
|
+
batch.accept();
|
|
2308
|
+
if (
|
|
2309
|
+
!batch.membershipChanged &&
|
|
2310
|
+
!batch.changedComponents.includes(RuntimeMaterialValue) &&
|
|
2311
|
+
!batch.changedComponents.includes(RuntimeMeshVertices)
|
|
2312
|
+
)
|
|
2313
|
+
continue;
|
|
2314
|
+
for (const index of batch.indices) {
|
|
2315
|
+
const entity = source.projection.entity(index);
|
|
2316
|
+
if (entity === undefined) {
|
|
2317
|
+
source.entities.delete(index);
|
|
2318
|
+
source.contentHandles.delete(index);
|
|
2319
|
+
} else {
|
|
2320
|
+
source.entities.set(index, entity);
|
|
2321
|
+
const handles: number[] = [];
|
|
2322
|
+
const world = worlds[worldId];
|
|
2323
|
+
if (world !== undefined) {
|
|
2324
|
+
const material = world.hasComponent(entity, RuntimeMaterialValue)
|
|
2325
|
+
? world.get(entity, RuntimeMaterialValue)
|
|
2326
|
+
: undefined;
|
|
2327
|
+
const mesh = world.hasComponent(entity, RuntimeMeshVertices)
|
|
2328
|
+
? world.get(entity, RuntimeMeshVertices)
|
|
2329
|
+
: undefined;
|
|
2330
|
+
if (material?.ok) handles.push(Number(material.value.asset));
|
|
2331
|
+
if (mesh?.ok) handles.push(Number(mesh.value.asset));
|
|
2332
|
+
}
|
|
2333
|
+
if (handles.length === 0) source.contentHandles.delete(index);
|
|
2334
|
+
else source.contentHandles.set(index, handles);
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2283
2338
|
entry.catalogEpoch = catalogEpoch;
|
|
2284
|
-
entry.instanceEpoch = instanceEpoch;
|
|
2285
2339
|
for (let worldId = 0; worldId < nextReadVersions.length; worldId += 1) {
|
|
2286
2340
|
const version = nextReadVersions[worldId];
|
|
2287
2341
|
if (version !== undefined) entry.readVersions[worldId] = version;
|
|
@@ -2328,11 +2382,13 @@ export class PersistentRenderScene {
|
|
|
2328
2382
|
this.stableSlotByEntity.clear();
|
|
2329
2383
|
}
|
|
2330
2384
|
if (this.gpuOwner !== world && this.gpuOwner !== detachedComposition?.token) return;
|
|
2331
|
-
|
|
2332
|
-
|
|
2385
|
+
// The GPU Scene is renderer-owned. A frame graph recorded for the current
|
|
2386
|
+
// device may retain its table bindings after a World detaches, while the
|
|
2387
|
+
// next attached composition can rebuild the same tables in place. Keep
|
|
2388
|
+
// that single scene resident until device replacement or renderer
|
|
2389
|
+
// disposal; retiring it here lets a reused graph submit destroyed buffers.
|
|
2333
2390
|
this.gpuOwner = undefined;
|
|
2334
|
-
this.
|
|
2335
|
-
this.gpuStatus = 'inactive';
|
|
2391
|
+
this.gpuStatus = this.gpuScene === undefined ? 'inactive' : 'resident';
|
|
2336
2392
|
}
|
|
2337
2393
|
|
|
2338
2394
|
/** Drop only device-owned tables; the CPU projection remains the recovery authority. */
|
|
@@ -2398,6 +2454,9 @@ export class PersistentRenderScene {
|
|
|
2398
2454
|
scene,
|
|
2399
2455
|
plan: composition.topology.plan(),
|
|
2400
2456
|
slots,
|
|
2457
|
+
worldKeys: composition.worldKeys,
|
|
2458
|
+
worldIdentities: composition.worlds.map((world) => world.identity),
|
|
2459
|
+
probeBlend: composition.probeProjection.recordBufferProjection(),
|
|
2401
2460
|
});
|
|
2402
2461
|
let published = false;
|
|
2403
2462
|
let released = false;
|
|
@@ -2569,11 +2628,13 @@ export class PersistentRenderScene {
|
|
|
2569
2628
|
plan: entry.topology.plan(),
|
|
2570
2629
|
slots: entry.projection.slotsSnapshot(),
|
|
2571
2630
|
worldKeys: entry.worldKeys,
|
|
2631
|
+
worldIdentities: entry.worlds.map((world) => world.identity),
|
|
2572
2632
|
structureMetrics: {
|
|
2573
2633
|
worldEntitiesScanned: this.worldEntitiesScanned,
|
|
2574
2634
|
sceneTableUploadBytes: this.sceneTableUploadBytes,
|
|
2575
2635
|
paletteUploadBytes: 0,
|
|
2576
2636
|
},
|
|
2637
|
+
probeBlend: entry.probeProjection.recordBufferProjection(),
|
|
2577
2638
|
};
|
|
2578
2639
|
}
|
|
2579
2640
|
|
|
@@ -2647,7 +2708,12 @@ export class PersistentRenderScene {
|
|
|
2647
2708
|
preserveVisibilityOnReorder = false,
|
|
2648
2709
|
): ExtractedFrame {
|
|
2649
2710
|
const previousEntry = this.composition;
|
|
2650
|
-
const
|
|
2711
|
+
const sourceStates = worlds.map(createRenderSourceState);
|
|
2712
|
+
const candidateFrame = buildCandidateFrame({
|
|
2713
|
+
kind: 'partial',
|
|
2714
|
+
entitiesByWorld: sourceStates.map((source) => new Set(source.entities.values())),
|
|
2715
|
+
});
|
|
2716
|
+
for (const source of sourceStates) source.batch.validate();
|
|
2651
2717
|
this.temporalCapture = undefined;
|
|
2652
2718
|
this.worldEntitiesScanned = candidateFrame.renderables.length;
|
|
2653
2719
|
const worldKeys = this.visibilityWorldKeysFor(worlds);
|
|
@@ -2675,38 +2741,14 @@ export class PersistentRenderScene {
|
|
|
2675
2741
|
this.invalidateActiveEntityRevision();
|
|
2676
2742
|
}
|
|
2677
2743
|
}
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
// primitive's slot/generation. Dispatch is remapped below to the sorted
|
|
2681
|
-
// renderable projection and remains frame-order independent.
|
|
2682
|
-
const sorted = candidateFrame.renderables
|
|
2683
|
-
.map((snapshot, sourceIndex) => ({ snapshot, sourceIndex }))
|
|
2684
|
-
.sort((left, right) => {
|
|
2685
|
-
const leftWorld = worldKeys[left.snapshot.worldId] ?? left.snapshot.worldId;
|
|
2686
|
-
const rightWorld = worldKeys[right.snapshot.worldId] ?? right.snapshot.worldId;
|
|
2687
|
-
return leftWorld - rightWorld || left.snapshot.entityKey - right.snapshot.entityKey;
|
|
2688
|
-
});
|
|
2689
|
-
const sortedRenderables = sorted.map(({ snapshot }) => snapshot);
|
|
2690
|
-
const renderableIndex = new Int32Array(candidateFrame.renderables.length);
|
|
2691
|
-
for (let index = 0; index < sorted.length; index += 1) {
|
|
2692
|
-
const sourceIndex = sorted[index]?.sourceIndex;
|
|
2693
|
-
if (sourceIndex !== undefined) renderableIndex[sourceIndex] = index;
|
|
2694
|
-
}
|
|
2695
|
-
const sortedDispatch = candidateFrame.dispatch.flatMap((entry) => {
|
|
2696
|
-
const index = renderableIndex[entry.renderableIndex];
|
|
2697
|
-
return index === undefined ? [] : [{ ...entry, renderableIndex: index }];
|
|
2698
|
-
});
|
|
2699
|
-
const stableCandidateFrame = {
|
|
2700
|
-
...candidateFrame,
|
|
2701
|
-
renderables: sortedRenderables,
|
|
2702
|
-
dispatch: sortedDispatch,
|
|
2703
|
-
};
|
|
2744
|
+
const stableCandidateFrame = candidateFrame;
|
|
2745
|
+
const renderables = candidateFrame.renderables;
|
|
2704
2746
|
const projection = previousEntry?.projection ?? new RenderScene();
|
|
2705
2747
|
if (previousEntry !== undefined) {
|
|
2706
2748
|
projection.remapWorlds(previousEntry.worlds.map((world) => worlds.indexOf(world)));
|
|
2707
2749
|
}
|
|
2708
2750
|
const desired = new Set(
|
|
2709
|
-
|
|
2751
|
+
renderables.map((snapshot) => identityKey(snapshot.worldId, snapshot.entityKey)),
|
|
2710
2752
|
);
|
|
2711
2753
|
const operations: RenderSceneOperation[] = [];
|
|
2712
2754
|
for (const slot of projection.slotsSnapshot()) {
|
|
@@ -2714,7 +2756,7 @@ export class PersistentRenderScene {
|
|
|
2714
2756
|
operations.push({ kind: 'remove', worldId: slot.worldId, entityKey: slot.entityKey });
|
|
2715
2757
|
}
|
|
2716
2758
|
}
|
|
2717
|
-
for (const snapshot of
|
|
2759
|
+
for (const snapshot of renderables) {
|
|
2718
2760
|
operations.push({
|
|
2719
2761
|
kind: 'update',
|
|
2720
2762
|
worldId: snapshot.worldId,
|
|
@@ -2723,6 +2765,22 @@ export class PersistentRenderScene {
|
|
|
2723
2765
|
});
|
|
2724
2766
|
}
|
|
2725
2767
|
const delta = projection.apply(operations);
|
|
2768
|
+
for (const snapshot of renderables) {
|
|
2769
|
+
const world = worlds[snapshot.worldId];
|
|
2770
|
+
if (world !== undefined && snapshot.instances !== undefined)
|
|
2771
|
+
this.options.instanceCollections?.accept(world, snapshot.entityKey, snapshot.instances);
|
|
2772
|
+
}
|
|
2773
|
+
this.options.instanceCollections?.retain(
|
|
2774
|
+
new Set(
|
|
2775
|
+
projection
|
|
2776
|
+
.slotsSnapshot()
|
|
2777
|
+
.flatMap((slot) =>
|
|
2778
|
+
slot.snapshot.instances?.collectionId === undefined
|
|
2779
|
+
? []
|
|
2780
|
+
: [slot.snapshot.instances.collectionId],
|
|
2781
|
+
),
|
|
2782
|
+
),
|
|
2783
|
+
);
|
|
2726
2784
|
this.stableSlotByEntity.clear();
|
|
2727
2785
|
for (const slot of projection.slotsSnapshot()) {
|
|
2728
2786
|
const stableWorld = worldKeys[slot.worldId] ?? slot.worldId;
|
|
@@ -2757,10 +2815,7 @@ export class PersistentRenderScene {
|
|
|
2757
2815
|
leases === undefined || leases.length !== worlds.length
|
|
2758
2816
|
? []
|
|
2759
2817
|
: worlds.map(createGlobalTransformChangeQuery),
|
|
2760
|
-
|
|
2761
|
-
leases === undefined || leases.length !== worlds.length
|
|
2762
|
-
? []
|
|
2763
|
-
: worlds.map(createRenderChangeQueries),
|
|
2818
|
+
sourceStates,
|
|
2764
2819
|
dispatchBySlot: dispatchEntriesBySlot(stableCandidateFrame, projection),
|
|
2765
2820
|
dispatchRevision: 0,
|
|
2766
2821
|
dispatchCache: undefined,
|
|
@@ -2768,8 +2823,8 @@ export class PersistentRenderScene {
|
|
|
2768
2823
|
pendingRenderableEntitiesByWorld: worlds.map(() => new Set<number>()),
|
|
2769
2824
|
unavailableSlots: new Set<number>(),
|
|
2770
2825
|
catalogEpoch,
|
|
2771
|
-
instanceEpoch: this.options.instanceCollections?.epoch ?? 0,
|
|
2772
2826
|
probeProjection: new ProbeBlendSceneProjection(),
|
|
2827
|
+
probeObjects: undefined,
|
|
2773
2828
|
temporalDemanded: frameDemandsTemporal(candidateFrame),
|
|
2774
2829
|
gpuDrivenSceneRequired: true,
|
|
2775
2830
|
};
|
|
@@ -2804,6 +2859,7 @@ export class PersistentRenderScene {
|
|
|
2804
2859
|
? projection.cullingWorldBounds(snapshot)
|
|
2805
2860
|
: projection.cullingWorldBoundsAt(slot);
|
|
2806
2861
|
});
|
|
2862
|
+
for (const source of sourceStates) source.batch.accept();
|
|
2807
2863
|
this.frameEpoch += 1;
|
|
2808
2864
|
this.visibilityFacetFrame = undefined;
|
|
2809
2865
|
this.visibilityProjectionCache = undefined;
|
|
@@ -2826,9 +2882,8 @@ export class PersistentRenderScene {
|
|
|
2826
2882
|
*/
|
|
2827
2883
|
private deriveFramePlan(
|
|
2828
2884
|
entry: PersistentCompositionEntry,
|
|
2829
|
-
|
|
2885
|
+
resourceFrame: ExtractedFrame,
|
|
2830
2886
|
): ExtractedFrame {
|
|
2831
|
-
const resourceFrame = buildCandidateFrame('none');
|
|
2832
2887
|
const cachedDispatch = entry.dispatchCache;
|
|
2833
2888
|
const dispatch =
|
|
2834
2889
|
cachedDispatch?.revision === entry.dispatchRevision
|
|
@@ -2938,27 +2993,41 @@ export class PersistentRenderScene {
|
|
|
2938
2993
|
] as [number, number, number],
|
|
2939
2994
|
};
|
|
2940
2995
|
const probes = frame.lightProbes ?? [];
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2996
|
+
const revision = entry.projection.revisionValue();
|
|
2997
|
+
if (entry.probeObjects?.revision !== revision) {
|
|
2998
|
+
const slots = entry.projection.slotsSnapshot();
|
|
2999
|
+
const value = Object.freeze(
|
|
3000
|
+
slots.map((slot) =>
|
|
3001
|
+
Object.freeze({
|
|
3002
|
+
objectKey: slot.slot,
|
|
3003
|
+
generation: slot.generation,
|
|
3004
|
+
position: [
|
|
3005
|
+
slot.snapshot.transform.world[12] ?? 0,
|
|
3006
|
+
slot.snapshot.transform.world[13] ?? 0,
|
|
3007
|
+
slot.snapshot.transform.world[14] ?? 0,
|
|
3008
|
+
] as const,
|
|
3009
|
+
}),
|
|
3010
|
+
),
|
|
3011
|
+
);
|
|
3012
|
+
entry.probeObjects = {
|
|
3013
|
+
revision,
|
|
3014
|
+
value,
|
|
3015
|
+
surfaceValue: Object.freeze(
|
|
3016
|
+
value.filter((_object, index) =>
|
|
3017
|
+
slots[index]?.snapshot.materials.some(
|
|
3018
|
+
(material) => material.surfaceModel === 'single-layer-medium',
|
|
3019
|
+
),
|
|
3020
|
+
),
|
|
3021
|
+
),
|
|
3022
|
+
};
|
|
2948
3023
|
}
|
|
2949
|
-
const
|
|
2950
|
-
objectKey: slot.slot,
|
|
2951
|
-
generation: slot.generation,
|
|
2952
|
-
position: [
|
|
2953
|
-
slot.snapshot.transform.world[12] ?? 0,
|
|
2954
|
-
slot.snapshot.transform.world[13] ?? 0,
|
|
2955
|
-
slot.snapshot.transform.world[14] ?? 0,
|
|
2956
|
-
],
|
|
2957
|
-
}));
|
|
3024
|
+
const surfaceOnly = probes.length === 0;
|
|
2958
3025
|
entry.probeProjection.apply({
|
|
2959
|
-
objects,
|
|
3026
|
+
objects: surfaceOnly ? entry.probeObjects.surfaceValue : entry.probeObjects.value,
|
|
2960
3027
|
probes,
|
|
2961
3028
|
sky,
|
|
3029
|
+
worldRevision: revision,
|
|
3030
|
+
...(surfaceOnly ? { retainSkyResidualRecords: true } : {}),
|
|
2962
3031
|
});
|
|
2963
3032
|
}
|
|
2964
3033
|
|