@forgeax/engine-render 0.1.33 → 0.1.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1062 -127
- package/dist/assembly/backend-contract.d.ts +2 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
- package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
- package/dist/assembly/canvas-draw-guard.d.ts +3 -0
- package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
- package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
- package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
- package/dist/assembly/device-feature-admission.d.ts +2 -2
- package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
- package/dist/assembly/factory.d.ts +1 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +6 -5
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
- package/dist/assembly/material-shader-policy.d.ts +16 -2
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/render-feature-post-processes.d.ts +6 -0
- package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
- package/dist/assembly/render-target-host.d.ts +5 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
- package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-inspection.d.ts +11 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -1
- package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
- package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +1 -1
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +2 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +2 -4
- package/dist/authoring.mjs.map +1 -1
- package/dist/barrel-distortion.d.ts +47 -0
- package/dist/barrel-distortion.d.ts.map +1 -0
- package/dist/chunk-3XUBWRY2.mjs +1842 -0
- package/dist/chunk-3XUBWRY2.mjs.map +1 -0
- package/dist/{chunk-OO3DRYK7.mjs → chunk-G6HDNGY7.mjs} +2400 -1767
- package/dist/chunk-G6HDNGY7.mjs.map +1 -0
- package/dist/{chunk-ZDQWGQW7.mjs → chunk-LM5IE7GF.mjs} +4 -4
- package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
- package/dist/{chunk-VOZWDM3L.mjs → chunk-LNIUIKQ7.mjs} +1514 -498
- package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
- package/dist/chunk-MXTWKZO4.mjs +3268 -0
- package/dist/chunk-MXTWKZO4.mjs.map +1 -0
- package/dist/chunk-MZ4C7EHF.mjs +6942 -0
- package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
- package/dist/chunk-RIPAEGI6.mjs +48 -0
- package/dist/chunk-RIPAEGI6.mjs.map +1 -0
- package/dist/{chunk-LEAXOMYJ.mjs → chunk-SGPUJW3F.mjs} +117 -5
- package/dist/chunk-SGPUJW3F.mjs.map +1 -0
- package/dist/{chunk-PA5DRJNI.mjs → chunk-X2KA6WHM.mjs} +29 -4
- package/dist/chunk-X2KA6WHM.mjs.map +1 -0
- package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
- package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
- package/dist/cloud/density.d.ts +55 -0
- package/dist/cloud/density.d.ts.map +1 -0
- package/dist/cloud/extract.d.ts +25 -0
- package/dist/cloud/extract.d.ts.map +1 -0
- package/dist/cloud/feature.d.ts +57 -0
- package/dist/cloud/feature.d.ts.map +1 -0
- package/dist/cloud/frame-context.d.ts +8 -0
- package/dist/cloud/frame-context.d.ts.map +1 -0
- package/dist/cloud/inspection.d.ts +59 -0
- package/dist/cloud/inspection.d.ts.map +1 -0
- package/dist/cloud/optics.d.ts +56 -0
- package/dist/cloud/optics.d.ts.map +1 -0
- package/dist/cloud/parameters.d.ts +73 -0
- package/dist/cloud/parameters.d.ts.map +1 -0
- package/dist/cloud/resources.d.ts +60 -0
- package/dist/cloud/resources.d.ts.map +1 -0
- package/dist/cloud/shadow.d.ts +42 -0
- package/dist/cloud/shadow.d.ts.map +1 -0
- package/dist/cloud/temporal.d.ts +74 -0
- package/dist/cloud/temporal.d.ts.map +1 -0
- package/dist/components/barrel-distortion.d.ts +13 -0
- package/dist/components/barrel-distortion.d.ts.map +1 -0
- package/dist/components/cloud-layer.d.ts +29 -0
- package/dist/components/cloud-layer.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +20 -6
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/construct-renderer.d.ts +1 -1
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +8406 -5785
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +19 -19
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/dynamic-geometry.d.ts +5 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/errors/cloud.d.ts +59 -0
- package/dist/errors/cloud.d.ts.map +1 -0
- package/dist/errors/render.d.ts +20 -5
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/examples/single-layer-medium-surface.d.ts +47 -0
- package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +5 -1
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/material-context.d.ts +7 -0
- package/dist/extract/material-context.d.ts.map +1 -0
- package/dist/features/barrel-distortion.d.ts +29 -0
- package/dist/features/barrel-distortion.d.ts.map +1 -0
- package/dist/features/error-reporting.d.ts +6 -2
- package/dist/features/error-reporting.d.ts.map +1 -1
- package/dist/features/host.d.ts +15 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/plan.d.ts +10 -0
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +5 -0
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +1 -0
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/targets.d.ts +2 -0
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +48 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +15 -7
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/glyph-text-layout-system.d.ts +1 -1
- package/dist/glyph-text-layout-system.d.ts.map +1 -1
- package/dist/gpu-dirty-ranges.d.ts +11 -0
- package/dist/gpu-dirty-ranges.d.ts.map +1 -0
- package/dist/gpu-driven/batch-topology.d.ts +17 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts +6 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster-material.d.ts +178 -0
- package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +47 -3
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/resource-allocation.d.ts +31 -0
- package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
- package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
- package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +26 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +5 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +2 -2
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/frame-resources.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +14 -5
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +30 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +780 -9
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +135 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instance-buffer-cache.d.ts +4 -4
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +47 -100
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +7 -8
- package/dist/internal.mjs.map +1 -1
- package/dist/pbr-pipeline.d.ts +22 -4
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
- package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
- package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
- package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
- package/dist/pipeline/standard-output/resources.d.ts +2 -2
- package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
- package/dist/pipeline/standard-output/types.d.ts +4 -2
- package/dist/pipeline/standard-output/types.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/publication/contract.d.ts +77 -0
- package/dist/publication/contract.d.ts.map +1 -0
- package/dist/publication/dependencies.d.ts +7 -0
- package/dist/publication/dependencies.d.ts.map +1 -0
- package/dist/publication/prepare-geometry.d.ts +9 -0
- package/dist/publication/prepare-geometry.d.ts.map +1 -0
- package/dist/publication/programs.d.ts +5 -0
- package/dist/publication/programs.d.ts.map +1 -0
- package/dist/publication/publisher.d.ts +33 -0
- package/dist/publication/publisher.d.ts.map +1 -0
- package/dist/publication/receiver.d.ts +29 -0
- package/dist/publication/receiver.d.ts.map +1 -0
- package/dist/publication/resource-scope.d.ts +18 -0
- package/dist/publication/resource-scope.d.ts.map +1 -0
- package/dist/publication/targets.d.ts +33 -0
- package/dist/publication/targets.d.ts.map +1 -0
- package/dist/publication/video.d.ts +5 -0
- package/dist/publication/video.d.ts.map +1 -0
- package/dist/record/barrel-distortion-frame.d.ts +15 -0
- package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
- package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
- package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
- package/dist/record/fold-buckets.d.ts +95 -0
- package/dist/record/fold-buckets.d.ts.map +1 -0
- package/dist/record/fold-instance-buffer.d.ts +6 -0
- package/dist/record/fold-instance-buffer.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +1 -0
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +43 -9
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +15 -65
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-draw-receipts.d.ts +11 -0
- package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +8 -0
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +2 -2
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +22 -6
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +14 -10
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +3 -16
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +13 -2
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/motion-blur-receipt.d.ts +11 -0
- package/dist/record/motion-blur-receipt.d.ts.map +1 -0
- package/dist/record/prepared-material-bindings.d.ts +3 -3
- package/dist/record/prepared-material-bindings.d.ts.map +1 -1
- package/dist/record/probe-blend-buffer.d.ts +16 -0
- package/dist/record/probe-blend-buffer.d.ts.map +1 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +24 -5
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -0
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/sprite-instance-buffer.d.ts +31 -0
- package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
- package/dist/record/target-capture-graph.d.ts +19 -0
- package/dist/record/target-capture-graph.d.ts.map +1 -0
- package/dist/record/typed-frame-graph.d.ts +24 -15
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +11 -3
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/record/volume-params.d.ts +9 -0
- package/dist/record/volume-params.d.ts.map +1 -0
- package/dist/recovery/render-system-candidate.d.ts +14 -4
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +46 -5
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +103 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +3 -2
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +18 -9
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-presentation.d.ts +23 -0
- package/dist/render-system-presentation.d.ts.map +1 -0
- package/dist/render-system-producer-roots.d.ts +10 -0
- package/dist/render-system-producer-roots.d.ts.map +1 -0
- package/dist/render-system-projections.d.ts +3 -2
- package/dist/render-system-projections.d.ts.map +1 -1
- package/dist/render-system-residency.d.ts +12 -0
- package/dist/render-system-residency.d.ts.map +1 -0
- package/dist/render-system.d.ts +22 -21
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/probe-blend.d.ts +27 -0
- package/dist/scene/probe-blend.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +18 -7
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/render-source.d.ts +42 -0
- package/dist/scene/render-source.d.ts.map +1 -0
- package/dist/scene/source-systems.d.ts +6 -0
- package/dist/scene/source-systems.d.ts.map +1 -0
- package/dist/ssao-buffers.d.ts +9 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/surface/dynamic-input.d.ts +133 -0
- package/dist/surface/dynamic-input.d.ts.map +1 -0
- package/dist/surface/gpu-driven.d.ts +41 -0
- package/dist/surface/gpu-driven.d.ts.map +1 -0
- package/dist/surface/submission-observation.d.ts +136 -0
- package/dist/surface/submission-observation.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/systems/skin-palette-types.d.ts +10 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -1
- package/dist/systems/transparent-dispatch.d.ts +2 -2
- package/dist/systems/transparent-dispatch.d.ts.map +1 -1
- package/dist/systems/transparent-sort-config.d.ts +2 -1
- package/dist/systems/transparent-sort-config.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts +13 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -7
- package/dist/temporal/inspection.d.ts.map +1 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
- package/dist/transmission/single-layer-medium.d.ts +89 -0
- package/dist/transmission/single-layer-medium.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +14 -2
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +9 -4
- package/dist/volume/component.d.ts.map +1 -1
- package/dist/volume/extract.d.ts +1 -1
- package/dist/volume/extract.d.ts.map +1 -1
- package/dist/volume/inspection.d.ts +2 -0
- package/dist/volume/inspection.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +4 -1
- package/dist/volume/passes.d.ts.map +1 -1
- package/dist/volume/resources.d.ts.map +1 -1
- package/package.json +22 -21
- package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
- package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
- package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
- package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
- package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
- package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
- package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
- package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
- package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
- package/src/__tests__/factory-contract.integration.test.ts +295 -45
- package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
- package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
- package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +5 -6
- package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
- package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
- package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
- package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
- package/src/__tests__/gpu-scene.unit.test.ts +119 -9
- package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
- package/src/__tests__/instances-culling.integration.test.ts +10 -36
- package/src/__tests__/instances-store.unit.test.ts +97 -305
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
- package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +145 -0
- package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
- package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
- package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
- package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
- package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
- package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +66 -8
- package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
- package/src/__tests__/probe-bindings.unit.test.ts +582 -1
- package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
- package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +8 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
- package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
- package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
- package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
- package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
- package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
- package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
- package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -8
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
- package/src/__tests__/resource-allocation.unit.test.ts +123 -0
- package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
- package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
- package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
- package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
- package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
- package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
- package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
- package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
- package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
- package/src/__tests__/temporal-performance.integration.test.ts +3 -3
- package/src/__tests__/visibility-instances.integration.test.ts +7 -19
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
- package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
- package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
- package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
- package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
- package/src/assembly/backend-contract.ts +30 -0
- package/src/assembly/barrel-distortion-inspection.ts +22 -0
- package/src/assembly/canvas-draw-guard.ts +11 -0
- package/src/assembly/cloud-shadow-entry.ts +22 -0
- package/src/assembly/device-feature-admission.ts +2 -2
- package/src/assembly/dynamic-geometry-host.ts +65 -37
- package/src/assembly/dynamic-geometry-runtime.ts +7 -1
- package/src/assembly/factory.ts +2 -30
- package/src/assembly/host-contract.ts +8 -5
- package/src/assembly/material/assembly.ts +25 -13
- package/src/assembly/material/pipeline-helpers.ts +53 -12
- package/src/assembly/material-shader-policy.ts +55 -0
- package/src/assembly/material-shader-prewarm.ts +21 -10
- package/src/assembly/recovery/device-loss-fanout.ts +13 -0
- package/src/assembly/recovery/renderer-recover.ts +50 -18
- package/src/assembly/render-feature-post-processes.ts +54 -0
- package/src/assembly/render-target-host.ts +57 -47
- package/src/assembly/renderer-facade.ts +7 -2
- package/src/assembly/renderer-feature-inspection.ts +8 -2
- package/src/assembly/renderer-frame-transaction.ts +23 -0
- package/src/assembly/renderer-inspection.ts +28 -0
- package/src/assembly/skin-palette-owner.ts +1 -1
- package/src/assembly/temporal-post-process-prewarm.ts +3 -3
- package/src/assembly/webgpu-pbr-ready.ts +9 -1
- package/src/assembly/webgpu-ready-per-pass.ts +104 -0
- package/src/assembly/webgpu-ready.ts +116 -62
- package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
- package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
- package/src/assembly/webgpu-renderer.ts +303 -313
- package/src/assembly/webgpu-vertex-layouts.ts +1 -1
- package/src/barrel-distortion.ts +247 -0
- package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
- package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
- package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
- package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
- package/src/cloud/density.ts +600 -0
- package/src/cloud/extract.ts +110 -0
- package/src/cloud/feature.ts +1810 -0
- package/src/cloud/frame-context.ts +42 -0
- package/src/cloud/inspection.ts +130 -0
- package/src/cloud/optics.ts +285 -0
- package/src/cloud/parameters.ts +255 -0
- package/src/cloud/resources.ts +122 -0
- package/src/cloud/shadow.ts +167 -0
- package/src/cloud/temporal.ts +226 -0
- package/src/components/barrel-distortion.ts +46 -0
- package/src/components/cloud-layer.ts +47 -0
- package/src/components/index.ts +2 -0
- package/src/components/instances.ts +18 -45
- package/src/components/sprite-instances.ts +1 -1
- package/src/construct-renderer.ts +1 -1
- package/src/device/gpu-residency.ts +26 -25
- package/src/dynamic-geometry.ts +12 -1
- package/src/errors/cloud.ts +103 -0
- package/src/errors/render.ts +47 -8
- package/src/examples/single-layer-medium-surface.ts +59 -0
- package/src/extract/camera.ts +15 -1
- package/src/extract/contracts.ts +5 -0
- package/src/extract/material-context.ts +21 -0
- package/src/features/barrel-distortion.ts +172 -0
- package/src/features/error-reporting.ts +26 -6
- package/src/features/host.ts +128 -19
- package/src/features/plan.ts +10 -0
- package/src/features/render-graph-contribution.ts +9 -0
- package/src/features/render-graph-raster.ts +45 -3
- package/src/features/targets.ts +66 -0
- package/src/features/types.ts +51 -0
- package/src/fullscreen-post-process-pass.ts +41 -9
- package/src/glyph-text-layout-system.ts +2 -2
- package/src/gpu-dirty-ranges.ts +48 -0
- package/src/gpu-driven/batch-topology.ts +53 -0
- package/src/gpu-driven/material-artifacts.ts +33 -25
- package/src/gpu-driven/prepared-draw.ts +12 -4
- package/src/gpu-driven/production-raster-material.ts +1894 -0
- package/src/gpu-driven/production-raster.ts +825 -784
- package/src/gpu-driven/resource-allocation.ts +142 -0
- package/src/gpu-driven/shadow-ownership.ts +71 -0
- package/src/gpu-driven/view-gpu.ts +164 -10
- package/src/gpu-scene.ts +75 -84
- package/src/hdrp-buffers.ts +4 -3
- package/src/ibl/frame-resources.ts +0 -1
- package/src/ibl/skylight-bind-group.ts +62 -32
- package/src/index.ts +205 -9
- package/src/inspection-types.ts +162 -0
- package/src/instance-buffer-cache.ts +4 -4
- package/src/instances.ts +152 -569
- package/src/pbr-pipeline.ts +230 -30
- package/src/pipeline/single-layer-medium-passes.ts +267 -0
- package/src/pipeline/standard-forward-lane.ts +313 -57
- package/src/pipeline/standard-output/graph.ts +8 -2
- package/src/pipeline/standard-output/lut-gpu.ts +3 -3
- package/src/pipeline/standard-output/resources.ts +2 -2
- package/src/pipeline/standard-output/types.ts +12 -1
- package/src/pipeline/standard-pipeline.ts +291 -18
- package/src/pipeline/standard-post.ts +90 -24
- package/src/pipeline-builder.ts +1 -1
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
- package/src/prepare/prepared-graphics-resolver.ts +2 -0
- package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
- package/src/publication/__tests__/features.integration.test.ts +122 -0
- package/src/publication/__tests__/programs.unit.test.ts +25 -0
- package/src/publication/__tests__/publication.integration.test.ts +370 -0
- package/src/publication/__tests__/targets.integration.test.ts +120 -0
- package/src/publication/__tests__/video.browser.test.ts +50 -0
- package/src/publication/contract.ts +104 -0
- package/src/publication/dependencies.ts +54 -0
- package/src/publication/prepare-geometry.ts +94 -0
- package/src/publication/programs.ts +45 -0
- package/src/publication/publisher.ts +618 -0
- package/src/publication/receiver.ts +297 -0
- package/src/publication/resource-scope.ts +31 -0
- package/src/publication/targets.ts +182 -0
- package/src/publication/video.ts +33 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +9 -11
- package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
- package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
- package/src/record/barrel-distortion-frame.ts +110 -0
- package/src/record/dynamic-geometry-consumption.ts +39 -9
- package/src/record/fold-buckets.ts +855 -0
- package/src/record/fold-instance-buffer.ts +51 -0
- package/src/record/frame-lighting.ts +36 -2
- package/src/record/frame-snapshot.ts +45 -9
- package/src/record/frame.ts +258 -1105
- package/src/record/gpu-draw-receipts.ts +38 -0
- package/src/record/gpu-timing.ts +48 -5
- package/src/record/helpers.ts +2 -2
- package/src/record/main-pass-geometry.ts +272 -84
- package/src/record/main-pass-material.ts +102 -36
- package/src/record/main-pass-sprite-draws.ts +13 -217
- package/src/record/main-pass.ts +164 -27
- package/src/record/motion-blur-receipt.ts +91 -0
- package/src/record/prepared-material-bindings.ts +11 -6
- package/src/record/probe-blend-buffer.ts +180 -0
- package/src/record/recovery-pipeline.ts +35 -3
- package/src/record/render-context.ts +41 -5
- package/src/record/shadow-pass.ts +30 -4
- package/src/record/skybox-post-pass.ts +28 -4
- package/src/record/sprite-instance-buffer.ts +155 -0
- package/src/record/target-capture-graph.ts +258 -0
- package/src/record/typed-frame-graph.ts +776 -340
- package/src/record/view-ubo.ts +27 -4
- package/src/record/volume-params.ts +225 -0
- package/src/recovery/render-system-candidate.ts +243 -50
- package/src/reflection/record-owner.ts +7 -3
- package/src/render-contract.ts +54 -5
- package/src/render-graph-primitives.ts +7 -1
- package/src/render-pipeline.ts +130 -0
- package/src/render-system-extract-tail.ts +90 -78
- package/src/render-system-extract.ts +76 -76
- package/src/render-system-presentation.ts +56 -0
- package/src/render-system-producer-roots.ts +96 -0
- package/src/render-system-projections.ts +3 -2
- package/src/render-system-residency.ts +159 -0
- package/src/render-system.ts +421 -408
- package/src/scene/probe-blend.ts +96 -4
- package/src/scene/render-scene.ts +416 -337
- package/src/scene/render-source.ts +90 -0
- package/src/scene/source-systems.ts +33 -0
- package/src/ssao-buffers.ts +95 -2
- package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
- package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
- package/src/surface/dynamic-input.ts +658 -0
- package/src/surface/gpu-driven.ts +147 -0
- package/src/surface/submission-observation.ts +517 -0
- package/src/systems/skin-palette-allocator.ts +5 -1
- package/src/systems/skin-palette-types.ts +11 -0
- package/src/systems/transparent-dispatch.ts +2 -2
- package/src/systems/transparent-sort-config.ts +3 -1
- package/src/temporal/gpu.ts +101 -17
- package/src/temporal/inspection.ts +7 -1
- package/src/temporal/standard-scene-data.ts +5 -0
- package/src/temporal/target-coverage-attachment.ts +4 -0
- package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
- package/src/transmission/single-layer-medium.ts +322 -0
- package/src/typed-render-graph-primitives.ts +70 -2
- package/src/volume/component.ts +10 -9
- package/src/volume/extract.ts +11 -5
- package/src/volume/inspection.ts +3 -0
- package/src/volume/passes.ts +87 -4
- package/src/volume/resources.ts +2 -1
- package/dist/chunk-3RTCJTH4.mjs +0 -1610
- package/dist/chunk-3RTCJTH4.mjs.map +0 -1
- package/dist/chunk-BLXGONR2.mjs.map +0 -1
- package/dist/chunk-ILQ5MEZF.mjs +0 -32
- package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
- package/dist/chunk-LEAXOMYJ.mjs.map +0 -1
- package/dist/chunk-NB2S7ZRX.mjs +0 -1783
- package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
- package/dist/chunk-NNQL7CB3.mjs +0 -1713
- package/dist/chunk-NNQL7CB3.mjs.map +0 -1
- package/dist/chunk-OO3DRYK7.mjs.map +0 -1
- package/dist/chunk-PA5DRJNI.mjs.map +0 -1
- package/dist/chunk-PLAXOOX5.mjs +0 -1907
- package/dist/chunk-PLAXOOX5.mjs.map +0 -1
- package/dist/chunk-RXZ3RGOU.mjs +0 -53
- package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
- package/dist/chunk-VOZWDM3L.mjs.map +0 -1
|
@@ -1,29 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import type {
|
|
1
|
+
import { RuntimeMaterialValue, RuntimeMeshVertices } from '@forgeax/engine-assets-runtime';
|
|
2
|
+
import type { EntityHandle, World } from '@forgeax/engine-ecs';
|
|
3
|
+
import type {
|
|
4
|
+
RenderReadLease,
|
|
5
|
+
RenderReadVersion,
|
|
6
|
+
StateProjection,
|
|
7
|
+
StateProjectionBatch,
|
|
8
|
+
} from '@forgeax/engine-ecs/projection';
|
|
4
9
|
import { box3, frustum, mat4 } from '@forgeax/engine-math';
|
|
5
10
|
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';
|
|
11
|
+
import { ChildOf, Children, GlobalTransform, MorphWeights } from '@forgeax/engine-scene';
|
|
13
12
|
import { Skin } from '@forgeax/engine-skinning';
|
|
14
13
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
15
|
-
import {
|
|
16
|
-
Instances,
|
|
17
|
-
Layer,
|
|
18
|
-
Lines,
|
|
19
|
-
MeshFilter,
|
|
20
|
-
MeshRenderer,
|
|
21
|
-
Points,
|
|
22
|
-
SortKey,
|
|
23
|
-
SpriteInstances,
|
|
24
|
-
SpriteRegionOverride,
|
|
25
|
-
Visibility,
|
|
26
|
-
} from '../components';
|
|
14
|
+
import { Instances, Lines, Points, SpriteInstances, Visibility } from '../components';
|
|
27
15
|
import type { DeviceScope, LifecycleResourceSpec } from '../device/device-scope';
|
|
28
16
|
import { gpuDrivenShadowDrawKey } from '../extract/gpu-driven';
|
|
29
17
|
import { motionBlurTemporalDemand } from '../features/motion-blur/motion-blur-params';
|
|
@@ -37,10 +25,12 @@ import type {
|
|
|
37
25
|
GpuDrivenStructureMetrics,
|
|
38
26
|
PersistentRenderSceneInspection,
|
|
39
27
|
} from '../inspection-types';
|
|
40
|
-
import type {
|
|
28
|
+
import type { InstanceProjectionStore } from '../instances';
|
|
41
29
|
import { fingerprintNumericArray, InstanceBoundsCache } from '../instances-derived-bounds';
|
|
42
30
|
import type { PointsLinesInspection } from '../points-lines/inspection';
|
|
43
31
|
import type { PointsLinesRetainedSnapshot } from '../points-lines/snapshot';
|
|
32
|
+
import type { PreparedRenderPublication } from '../publication/receiver';
|
|
33
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
44
34
|
import { worldEntityKey } from '../record/frame-snapshot';
|
|
45
35
|
import {
|
|
46
36
|
type ReflectionProbeFact,
|
|
@@ -62,7 +52,11 @@ import {
|
|
|
62
52
|
type TransmissionDemand,
|
|
63
53
|
type TransmissionDemandOperation,
|
|
64
54
|
} from '../transmission/projection';
|
|
65
|
-
import {
|
|
55
|
+
import {
|
|
56
|
+
type ProbeBlendBufferProjection,
|
|
57
|
+
ProbeBlendSceneProjection,
|
|
58
|
+
type ProbeSceneObjectInput,
|
|
59
|
+
} from './probe-blend';
|
|
66
60
|
import type {
|
|
67
61
|
RenderSceneApplyResult,
|
|
68
62
|
RenderSceneBounds,
|
|
@@ -72,6 +66,13 @@ import type {
|
|
|
72
66
|
RenderSceneResyncReason,
|
|
73
67
|
RenderSceneSlot,
|
|
74
68
|
} from './render-scene-types';
|
|
69
|
+
import {
|
|
70
|
+
createGlobalTransformChangeQuery,
|
|
71
|
+
createRenderSourceState,
|
|
72
|
+
type GlobalTransformChangeQuery,
|
|
73
|
+
isRenderableMember,
|
|
74
|
+
RENDERABLE_SOURCE_COMPONENTS,
|
|
75
|
+
} from './render-source';
|
|
75
76
|
import { buildShadowFrusta } from './shadow-visibility';
|
|
76
77
|
import { createVisibilityBudget, type VisibilityBudget } from './visibility/budget';
|
|
77
78
|
import {
|
|
@@ -114,8 +115,6 @@ interface WorldTransformSpan {
|
|
|
114
115
|
readonly worlds: Readonly<Float32Array>;
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
type GlobalTransformChangeQuery = Query<readonly [typeof GlobalTransform]>;
|
|
118
|
-
|
|
119
118
|
function sameInstanceIdentitySet(
|
|
120
119
|
current: Uint32Array | undefined,
|
|
121
120
|
previous: Uint32Array | undefined,
|
|
@@ -402,16 +401,33 @@ export class RenderScene {
|
|
|
402
401
|
return this.emptyResult();
|
|
403
402
|
}
|
|
404
403
|
|
|
405
|
-
|
|
404
|
+
// Prepare every potentially fallible payload copy before mutating retained
|
|
405
|
+
// columns. The commit loop below only uses owned POD and borrowed numeric spans.
|
|
406
|
+
const preparedOperations = operations.map((operation): RenderSceneOperation => {
|
|
407
|
+
if (operation.kind === 'remove') return operation;
|
|
406
408
|
if (
|
|
407
|
-
operation.kind === 'update' &&
|
|
408
409
|
operation.snapshot !== undefined &&
|
|
409
410
|
(operation.worldId !== operation.snapshot.worldId ||
|
|
410
411
|
operation.entityKey !== operation.snapshot.entityKey)
|
|
411
412
|
) {
|
|
412
413
|
throw new RangeError('RenderScene update identity must match its source snapshot');
|
|
413
414
|
}
|
|
414
|
-
|
|
415
|
+
return {
|
|
416
|
+
...operation,
|
|
417
|
+
...(operation.snapshot === undefined ? {} : { snapshot: ownSnapshot(operation.snapshot) }),
|
|
418
|
+
...(operation.instances === undefined
|
|
419
|
+
? {}
|
|
420
|
+
: {
|
|
421
|
+
instances: {
|
|
422
|
+
...operation.instances,
|
|
423
|
+
transforms: new Float32Array(operation.instances.transforms),
|
|
424
|
+
...(operation.instances.generations === undefined
|
|
425
|
+
? {}
|
|
426
|
+
: { generations: new Uint32Array(operation.instances.generations) }),
|
|
427
|
+
},
|
|
428
|
+
}),
|
|
429
|
+
};
|
|
430
|
+
});
|
|
415
431
|
this.deltaFrames += 1;
|
|
416
432
|
this.renderableScans = operations.length;
|
|
417
433
|
const pendingByWorld = new Map<number, Map<number, PendingIdentity>>();
|
|
@@ -453,7 +469,7 @@ export class RenderScene {
|
|
|
453
469
|
}
|
|
454
470
|
}
|
|
455
471
|
};
|
|
456
|
-
for (const operation of
|
|
472
|
+
for (const operation of preparedOperations) {
|
|
457
473
|
const pending = pendingFor(operation.worldId, operation.entityKey);
|
|
458
474
|
if (operation.kind === 'remove') {
|
|
459
475
|
pending.current = undefined;
|
|
@@ -462,7 +478,7 @@ export class RenderScene {
|
|
|
462
478
|
}
|
|
463
479
|
if (operation.snapshot !== undefined) {
|
|
464
480
|
const previousMaterials = pending.current?.materials;
|
|
465
|
-
const next =
|
|
481
|
+
const next = operation.snapshot;
|
|
466
482
|
pending.current =
|
|
467
483
|
previousMaterials !== undefined &&
|
|
468
484
|
previousMaterials.length === next.materials.length &&
|
|
@@ -478,13 +494,7 @@ export class RenderScene {
|
|
|
478
494
|
if (operation.instances !== undefined) {
|
|
479
495
|
pending.current = {
|
|
480
496
|
...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
|
-
},
|
|
497
|
+
instances: operation.instances,
|
|
488
498
|
};
|
|
489
499
|
pending.instanceChanged = true;
|
|
490
500
|
}
|
|
@@ -753,6 +763,11 @@ export class RenderScene {
|
|
|
753
763
|
return this.slotSnapshot;
|
|
754
764
|
}
|
|
755
765
|
|
|
766
|
+
/** Cheap owner revision for retained derived projections. */
|
|
767
|
+
revisionValue(): number {
|
|
768
|
+
return this.revision;
|
|
769
|
+
}
|
|
770
|
+
|
|
756
771
|
slot(worldId: number, entityKey: number): RenderSceneSlot | undefined {
|
|
757
772
|
return this.lookup(worldId, entityKey);
|
|
758
773
|
}
|
|
@@ -1047,10 +1062,10 @@ export class RenderScene {
|
|
|
1047
1062
|
export interface PersistentRenderSceneOptions {
|
|
1048
1063
|
readonly getDevice?: (() => RhiDevice) | undefined;
|
|
1049
1064
|
readonly onGpuError?: ((error: RhiError) => void) | undefined;
|
|
1050
|
-
readonly
|
|
1065
|
+
readonly onRuntimeAssetChange?: ((worldId: number, handle: number) => void) | undefined;
|
|
1051
1066
|
readonly configuredQueryBudget?: number | undefined;
|
|
1052
|
-
/**
|
|
1053
|
-
readonly instanceCollections?:
|
|
1067
|
+
/** Instance projection accepted by the same World source update flow. */
|
|
1068
|
+
readonly instanceCollections?: InstanceProjectionStore | undefined;
|
|
1054
1069
|
}
|
|
1055
1070
|
|
|
1056
1071
|
export interface PersistentGpuDrivenState {
|
|
@@ -1059,7 +1074,11 @@ export interface PersistentGpuDrivenState {
|
|
|
1059
1074
|
readonly slots: readonly RenderSceneSlot[];
|
|
1060
1075
|
/** Stable renderer-local World keys aligned with RenderSceneSlot.worldId. */
|
|
1061
1076
|
readonly worldKeys?: readonly number[];
|
|
1077
|
+
/** Public World identities aligned with RenderSceneSlot.worldId. */
|
|
1078
|
+
readonly worldIdentities?: readonly string[];
|
|
1062
1079
|
readonly structureMetrics?: GpuDrivenStructureMetrics;
|
|
1080
|
+
/** Stable retained ProbeBlend upload projection from the Scene owner. */
|
|
1081
|
+
readonly probeBlend?: ProbeBlendBufferProjection;
|
|
1063
1082
|
}
|
|
1064
1083
|
|
|
1065
1084
|
export interface CpuDirectViewInput {
|
|
@@ -1127,7 +1146,7 @@ type PersistentGpuSceneInspection = PersistentRenderSceneInspection['gpu'];
|
|
|
1127
1146
|
|
|
1128
1147
|
interface PersistentCompositionEntry {
|
|
1129
1148
|
readonly token: object;
|
|
1130
|
-
readonly worlds: readonly
|
|
1149
|
+
readonly worlds: readonly RenderResourceScope[];
|
|
1131
1150
|
readonly projection: RenderScene;
|
|
1132
1151
|
readonly topology: BatchTopology;
|
|
1133
1152
|
readonly transmissionDemand: PersistentTransmissionDemandProjection;
|
|
@@ -1137,7 +1156,11 @@ interface PersistentCompositionEntry {
|
|
|
1137
1156
|
readonly readVersions: RenderReadVersion[];
|
|
1138
1157
|
readonly leaseIdentities: readonly string[];
|
|
1139
1158
|
readonly transformQueries: readonly GlobalTransformChangeQuery[];
|
|
1140
|
-
readonly
|
|
1159
|
+
readonly sourceStates: readonly {
|
|
1160
|
+
projection: StateProjection;
|
|
1161
|
+
entities: Map<number, EntityHandle>;
|
|
1162
|
+
contentHandles: Map<number, readonly number[]>;
|
|
1163
|
+
}[];
|
|
1141
1164
|
readonly dispatchBySlot: Map<number, readonly DispatchEntry[]>;
|
|
1142
1165
|
dispatchRevision: number;
|
|
1143
1166
|
dispatchCache: { readonly revision: number; readonly value: DispatchEntry[] } | undefined;
|
|
@@ -1147,81 +1170,18 @@ interface PersistentCompositionEntry {
|
|
|
1147
1170
|
/** Slots retained for recovery but excluded from direct and indirect submission. */
|
|
1148
1171
|
readonly unavailableSlots: Set<number>;
|
|
1149
1172
|
catalogEpoch: number;
|
|
1150
|
-
instanceEpoch: number;
|
|
1151
1173
|
readonly probeProjection: ProbeBlendSceneProjection;
|
|
1174
|
+
probeObjects:
|
|
1175
|
+
| {
|
|
1176
|
+
readonly revision: number;
|
|
1177
|
+
readonly value: readonly ProbeSceneObjectInput[];
|
|
1178
|
+
readonly surfaceValue: readonly ProbeSceneObjectInput[];
|
|
1179
|
+
}
|
|
1180
|
+
| undefined;
|
|
1152
1181
|
temporalDemanded: boolean;
|
|
1153
1182
|
gpuDrivenSceneRequired: boolean;
|
|
1154
1183
|
}
|
|
1155
1184
|
|
|
1156
|
-
// Retained geometry consumes these component changes. Camera, lighting and
|
|
1157
|
-
// environment facts are freshly extracted by deriveFramePlan on every draw;
|
|
1158
|
-
// their edits must not recreate unrelated geometry or its submission history.
|
|
1159
|
-
const RENDERABLE_SOURCE_COMPONENTS = [
|
|
1160
|
-
GlobalTransform,
|
|
1161
|
-
ChildOf,
|
|
1162
|
-
MeshFilter,
|
|
1163
|
-
MeshRenderer,
|
|
1164
|
-
Instances,
|
|
1165
|
-
SpriteInstances,
|
|
1166
|
-
SpriteRegionOverride,
|
|
1167
|
-
Skin,
|
|
1168
|
-
Layer,
|
|
1169
|
-
Visibility,
|
|
1170
|
-
MorphWeights,
|
|
1171
|
-
Points,
|
|
1172
|
-
Lines,
|
|
1173
|
-
SortKey,
|
|
1174
|
-
] 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
|
-
function createGlobalTransformChangeQuery(world: World): GlobalTransformChangeQuery {
|
|
1191
|
-
const result = world.query({ read: [GlobalTransform], changed: [GlobalTransform] });
|
|
1192
|
-
if (!result.ok) throw result.error;
|
|
1193
|
-
const query = result.value as GlobalTransformChangeQuery;
|
|
1194
|
-
for (const _span of query.spans().unwrap()) {
|
|
1195
|
-
// The full rebuild consumed these values; establish the observation baseline.
|
|
1196
|
-
}
|
|
1197
|
-
return query;
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
function createRenderChangeQueries(world: World): ReadonlyMap<number, Query> {
|
|
1201
|
-
const queries = new Map<number, Query>();
|
|
1202
|
-
for (const component of RENDERABLE_SOURCE_COMPONENTS) {
|
|
1203
|
-
if (component === GlobalTransform) continue;
|
|
1204
|
-
const result = world.query({ read: [component], changed: [component] });
|
|
1205
|
-
if (!result.ok) throw result.error;
|
|
1206
|
-
const query = result.value as Query;
|
|
1207
|
-
// The initial full extraction has already consumed this change evidence.
|
|
1208
|
-
// Keep the query compiled so subsequent frames iterate only rows whose
|
|
1209
|
-
// component version changed.
|
|
1210
|
-
for (const _span of query.spans().unwrap()) {
|
|
1211
|
-
// Establish the observation baseline.
|
|
1212
|
-
}
|
|
1213
|
-
queries.set(componentId(component), query);
|
|
1214
|
-
}
|
|
1215
|
-
return queries;
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
function collectRenderableEntities(world: World): ReadonlySet<number> {
|
|
1219
|
-
const result = new Set<number>();
|
|
1220
|
-
const query = world.query({ read: [MeshRenderer], with: [Transform, MeshFilter] }).unwrap();
|
|
1221
|
-
for (const row of query) result.add(row.entity as number);
|
|
1222
|
-
return result;
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
1185
|
function sourceMembershipChanged(world: World, slot: RenderSceneSlot): boolean {
|
|
1226
1186
|
const entity = slot.entityKey as EntityHandle;
|
|
1227
1187
|
const snapshot = slot.snapshot;
|
|
@@ -1576,7 +1536,7 @@ export class PersistentRenderScene {
|
|
|
1576
1536
|
return this.visibilityBudget;
|
|
1577
1537
|
}
|
|
1578
1538
|
|
|
1579
|
-
private visibilityWorldKey(world:
|
|
1539
|
+
private visibilityWorldKey(world: RenderResourceScope | undefined, fallback: number): number {
|
|
1580
1540
|
if (world === undefined) return fallback;
|
|
1581
1541
|
const existing = this.visibilityWorldKeys.get(world.identity);
|
|
1582
1542
|
if (existing !== undefined) return existing;
|
|
@@ -1586,12 +1546,12 @@ export class PersistentRenderScene {
|
|
|
1586
1546
|
return key;
|
|
1587
1547
|
}
|
|
1588
1548
|
|
|
1589
|
-
private worldKeyAt(worlds: readonly
|
|
1549
|
+
private worldKeyAt(worlds: readonly RenderResourceScope[], worldId: number): number {
|
|
1590
1550
|
return this.visibilityWorldKey(worlds[worldId], worldId);
|
|
1591
1551
|
}
|
|
1592
1552
|
|
|
1593
1553
|
/** Stable World routing keys for the current worlds[] frame projection. */
|
|
1594
|
-
visibilityWorldKeysFor(worlds: readonly
|
|
1554
|
+
visibilityWorldKeysFor(worlds: readonly RenderResourceScope[]): readonly number[] {
|
|
1595
1555
|
return worlds.map((world, worldId) => this.visibilityWorldKey(world, worldId));
|
|
1596
1556
|
}
|
|
1597
1557
|
|
|
@@ -1600,6 +1560,10 @@ export class PersistentRenderScene {
|
|
|
1600
1560
|
return this.composition?.projection.slotsSnapshot() ?? [];
|
|
1601
1561
|
}
|
|
1602
1562
|
|
|
1563
|
+
compositionSlot(worldId: number, entityKey: number): RenderSceneSlot | undefined {
|
|
1564
|
+
return this.composition?.projection.slot(worldId, entityKey);
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1603
1567
|
shadowCasterProjection(): PersistentShadowCasterProjection | undefined {
|
|
1604
1568
|
return this.shadowProjection;
|
|
1605
1569
|
}
|
|
@@ -1610,7 +1574,7 @@ export class PersistentRenderScene {
|
|
|
1610
1574
|
}
|
|
1611
1575
|
|
|
1612
1576
|
private stableEntityKey(
|
|
1613
|
-
worlds: readonly
|
|
1577
|
+
worlds: readonly RenderResourceScope[],
|
|
1614
1578
|
renderable: Pick<RenderableSnapshot, 'worldId' | 'entityKey'>,
|
|
1615
1579
|
): number {
|
|
1616
1580
|
return worldEntityKey(this.worldKeyAt(worlds, renderable.worldId), renderable.entityKey);
|
|
@@ -1618,7 +1582,7 @@ export class PersistentRenderScene {
|
|
|
1618
1582
|
|
|
1619
1583
|
/** Feed the facet from extracted renderables using persistent slot identity. */
|
|
1620
1584
|
updateVisibilityFacet(
|
|
1621
|
-
worlds: readonly
|
|
1585
|
+
worlds: readonly RenderResourceScope[],
|
|
1622
1586
|
camera: CameraSnapshot | undefined,
|
|
1623
1587
|
renderables: readonly RenderableSnapshot[],
|
|
1624
1588
|
): void {
|
|
@@ -1678,7 +1642,7 @@ export class PersistentRenderScene {
|
|
|
1678
1642
|
* visible through `decideVisibility`.
|
|
1679
1643
|
*/
|
|
1680
1644
|
projectVisibility(
|
|
1681
|
-
worlds: readonly
|
|
1645
|
+
worlds: readonly RenderResourceScope[],
|
|
1682
1646
|
camera: CameraSnapshot | undefined,
|
|
1683
1647
|
renderables: readonly RenderableSnapshot[],
|
|
1684
1648
|
dispatch: readonly DispatchEntry[],
|
|
@@ -1852,6 +1816,77 @@ export class PersistentRenderScene {
|
|
|
1852
1816
|
return this.reflectionProbes.snapshot();
|
|
1853
1817
|
}
|
|
1854
1818
|
|
|
1819
|
+
consumePublication(input: PreparedRenderPublication): ExtractedFrame {
|
|
1820
|
+
const { resources, packet, frame } = input;
|
|
1821
|
+
let entry = this.composition;
|
|
1822
|
+
if (entry === undefined || packet.baseline) {
|
|
1823
|
+
this.invalidate();
|
|
1824
|
+
const projection = new RenderScene();
|
|
1825
|
+
entry = {
|
|
1826
|
+
token: {},
|
|
1827
|
+
worlds: [resources],
|
|
1828
|
+
projection,
|
|
1829
|
+
topology: new BatchTopology(),
|
|
1830
|
+
transmissionDemand: new PersistentTransmissionDemandProjection(),
|
|
1831
|
+
hiddenEntityReports: [],
|
|
1832
|
+
worldKeys: this.visibilityWorldKeysFor([resources]),
|
|
1833
|
+
readVersions: [],
|
|
1834
|
+
leaseIdentities: [],
|
|
1835
|
+
transformQueries: [],
|
|
1836
|
+
sourceStates: [],
|
|
1837
|
+
dispatchBySlot: new Map(),
|
|
1838
|
+
dispatchRevision: 0,
|
|
1839
|
+
dispatchCache: undefined,
|
|
1840
|
+
skinConsumersByJoint: new Map(),
|
|
1841
|
+
pendingRenderableEntitiesByWorld: [],
|
|
1842
|
+
unavailableSlots: new Set(),
|
|
1843
|
+
catalogEpoch: 0,
|
|
1844
|
+
probeProjection: new ProbeBlendSceneProjection(),
|
|
1845
|
+
probeObjects: undefined,
|
|
1846
|
+
temporalDemanded: false,
|
|
1847
|
+
gpuDrivenSceneRequired: true,
|
|
1848
|
+
};
|
|
1849
|
+
this.composition = entry;
|
|
1850
|
+
this.fullRebuilds++;
|
|
1851
|
+
this.lastResyncReason = 'attach';
|
|
1852
|
+
}
|
|
1853
|
+
this.worldEntitiesScanned = 0;
|
|
1854
|
+
this.sceneTableUploadBytes = 0;
|
|
1855
|
+
const removedDemand: TransmissionDemandOperation[] = [];
|
|
1856
|
+
for (const operation of input.operations) {
|
|
1857
|
+
if (operation.kind !== 'remove' && operation.snapshot === undefined) continue;
|
|
1858
|
+
const previous = entry.projection.slot(0, operation.entityKey);
|
|
1859
|
+
for (let index = 0; index < (previous?.snapshot.materials.length ?? 0); index++)
|
|
1860
|
+
removedDemand.push({ kind: 'remove', key: `0:${operation.entityKey}:${index}` });
|
|
1861
|
+
}
|
|
1862
|
+
const delta = entry.projection.apply(input.operations);
|
|
1863
|
+
for (const removed of delta.removedSlots) {
|
|
1864
|
+
entry.dispatchBySlot.delete(removed.slot);
|
|
1865
|
+
this.stableSlotByEntity.delete(worldEntityKey(entry.worldKeys[0] ?? 0, removed.entityKey));
|
|
1866
|
+
}
|
|
1867
|
+
for (const recreated of delta.recreatedSlots) entry.dispatchBySlot.delete(recreated.slot);
|
|
1868
|
+
for (const [slot, dispatch] of dispatchEntriesBySlot(frame, entry.projection))
|
|
1869
|
+
entry.dispatchBySlot.set(slot, dispatch);
|
|
1870
|
+
if (frame.renderables.length || packet.removed.length) {
|
|
1871
|
+
entry.dispatchRevision++;
|
|
1872
|
+
entry.dispatchCache = undefined;
|
|
1873
|
+
this.visibilityFacets.clear();
|
|
1874
|
+
this.invalidateActiveEntityRevision();
|
|
1875
|
+
}
|
|
1876
|
+
for (const slot of [...delta.createdSlots, ...delta.updatedSlots, ...delta.recreatedSlots])
|
|
1877
|
+
this.stableSlotByEntity.set(worldEntityKey(entry.worldKeys[0] ?? 0, slot.entityKey), slot);
|
|
1878
|
+
entry.transmissionDemand.apply([
|
|
1879
|
+
...removedDemand,
|
|
1880
|
+
...transmissionDemandOperations(frame.renderables),
|
|
1881
|
+
]);
|
|
1882
|
+
entry.topology.apply(delta);
|
|
1883
|
+
this.syncGpuOwner(entry.token, entry.projection, delta);
|
|
1884
|
+
if (input.operations.length) this.deltaFrames++;
|
|
1885
|
+
else this.noChangeFrames++;
|
|
1886
|
+
this.transformUpdates += delta.updated;
|
|
1887
|
+
return this.deriveFramePlan(entry, frame);
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1855
1890
|
extractComposition(
|
|
1856
1891
|
worlds: readonly World[],
|
|
1857
1892
|
owner: { readonly cameraOwner: number; readonly resourceOwner: number },
|
|
@@ -1865,7 +1900,7 @@ export class PersistentRenderScene {
|
|
|
1865
1900
|
const sameWorldSet =
|
|
1866
1901
|
entry !== undefined &&
|
|
1867
1902
|
entry.worlds.length === worlds.length &&
|
|
1868
|
-
entry.worlds.every((world) => worlds.
|
|
1903
|
+
entry.worlds.every((world) => worlds.some((local) => local === world));
|
|
1869
1904
|
const worldOrderChanged =
|
|
1870
1905
|
entry !== undefined &&
|
|
1871
1906
|
sameWorldSet &&
|
|
@@ -1899,7 +1934,6 @@ export class PersistentRenderScene {
|
|
|
1899
1934
|
preserveVisibilityOnReorder,
|
|
1900
1935
|
);
|
|
1901
1936
|
}
|
|
1902
|
-
let requiresSourceRefresh = false;
|
|
1903
1937
|
const changedEntitiesByWorld = worlds.map(
|
|
1904
1938
|
(_, worldId) => new Set(entry.pendingRenderableEntitiesByWorld[worldId] ?? []),
|
|
1905
1939
|
);
|
|
@@ -1912,171 +1946,144 @@ export class PersistentRenderScene {
|
|
|
1912
1946
|
contentChangedByWorld[slot.worldId]?.add(slot.entityKey);
|
|
1913
1947
|
}
|
|
1914
1948
|
}
|
|
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
1949
|
const nextReadVersions = entry.readVersions.slice();
|
|
1927
|
-
const
|
|
1928
|
-
const structuralComponentIdsByWorld = worlds.map(() => new Set<number>());
|
|
1929
|
-
let currentRenderableEntitiesByWorld: readonly (ReadonlySet<number> | undefined)[] | undefined;
|
|
1950
|
+
const sourceBatches: StateProjectionBatch[] = [];
|
|
1930
1951
|
const removedSlots: RenderSceneSlot[] = [];
|
|
1931
|
-
|
|
1952
|
+
const transformSpans: WorldTransformSpan[] = [];
|
|
1953
|
+
for (let worldId = 0; worldId < worlds.length; worldId++) {
|
|
1932
1954
|
const world = worlds[worldId];
|
|
1933
|
-
|
|
1934
|
-
const lease = leases
|
|
1935
|
-
if (lease === undefined || entry.leaseIdentities[worldId] !== lease.worldIdentity) {
|
|
1936
|
-
requiresSourceRefresh = true;
|
|
1937
|
-
break;
|
|
1938
|
-
}
|
|
1955
|
+
const source = entry.sourceStates[worldId];
|
|
1956
|
+
const lease = leases[worldId];
|
|
1939
1957
|
const version = entry.readVersions[worldId];
|
|
1940
|
-
if (
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
if (
|
|
1952
|
-
|
|
1958
|
+
if (
|
|
1959
|
+
world === undefined ||
|
|
1960
|
+
source === undefined ||
|
|
1961
|
+
lease === undefined ||
|
|
1962
|
+
version === undefined
|
|
1963
|
+
)
|
|
1964
|
+
continue;
|
|
1965
|
+
const read = lease.readChanges(version);
|
|
1966
|
+
nextReadVersions[worldId] = read.version;
|
|
1967
|
+
const changed = changedEntitiesByWorld[worldId];
|
|
1968
|
+
const content = contentChangedByWorld[worldId];
|
|
1969
|
+
if (changed === undefined || content === undefined) continue;
|
|
1970
|
+
if (version.structureEpoch !== read.version.structureEpoch) {
|
|
1971
|
+
this.visibilityFacets.clear();
|
|
1972
|
+
this.invalidateActiveEntityRevision();
|
|
1953
1973
|
}
|
|
1954
|
-
const
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1974
|
+
const batch = source.projection.read();
|
|
1975
|
+
sourceBatches.push(batch);
|
|
1976
|
+
this.worldEntitiesScanned += batch.scannedRows;
|
|
1977
|
+
const dependencyVisited = new Set<number>();
|
|
1978
|
+
const runtimeAssets = new Set<number>();
|
|
1979
|
+
const runtimeContentChanged =
|
|
1980
|
+
batch.membershipChanged ||
|
|
1981
|
+
batch.changedComponents.includes(RuntimeMaterialValue) ||
|
|
1982
|
+
batch.changedComponents.includes(RuntimeMeshVertices);
|
|
1983
|
+
const contentComponents = RENDERABLE_SOURCE_COMPONENTS.filter(
|
|
1984
|
+
(component) => component !== Instances && batch.changedComponents.includes(component),
|
|
1985
|
+
);
|
|
1986
|
+
const instancesChanged = batch.changedComponents.includes(Instances);
|
|
1987
|
+
const reconcileIdentities =
|
|
1988
|
+
batch.membershipChanged ||
|
|
1989
|
+
runtimeContentChanged ||
|
|
1990
|
+
contentComponents.length > 0 ||
|
|
1991
|
+
instancesChanged;
|
|
1992
|
+
for (const index of reconcileIdentities ? batch.indices : []) {
|
|
1993
|
+
const previous = source.entities.get(index);
|
|
1994
|
+
const current = source.projection.entity(index);
|
|
1995
|
+
if (runtimeContentChanged) {
|
|
1996
|
+
const runtimeHandles = new Set(source.contentHandles.get(index));
|
|
1997
|
+
if (current !== undefined) {
|
|
1998
|
+
const material = world.hasComponent(current, RuntimeMaterialValue)
|
|
1999
|
+
? world.get(current, RuntimeMaterialValue)
|
|
2000
|
+
: undefined;
|
|
2001
|
+
const mesh = world.hasComponent(current, RuntimeMeshVertices)
|
|
2002
|
+
? world.get(current, RuntimeMeshVertices)
|
|
2003
|
+
: undefined;
|
|
2004
|
+
if (material?.ok) runtimeHandles.add(Number(material.value.asset));
|
|
2005
|
+
if (mesh?.ok) runtimeHandles.add(Number(mesh.value.asset));
|
|
1964
2006
|
}
|
|
2007
|
+
for (const handle of runtimeHandles) runtimeAssets.add(handle);
|
|
1965
2008
|
}
|
|
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
|
-
}
|
|
2009
|
+
if (previous !== undefined) {
|
|
2010
|
+
const slot = entry.projection.slot(worldId, previous);
|
|
2011
|
+
if (
|
|
2012
|
+
batch.membershipChanged &&
|
|
2013
|
+
slot !== undefined &&
|
|
2014
|
+
(current !== previous || !isRenderableMember(world, previous))
|
|
2015
|
+
) {
|
|
2016
|
+
removedSlots.push(slot);
|
|
2017
|
+
changed.add(previous);
|
|
1994
2018
|
}
|
|
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)) ??
|
|
2019
|
+
for (const consumer of entry.skinConsumersByJoint.get(skinJointKey(worldId, previous)) ??
|
|
2017
2020
|
[]) {
|
|
2018
|
-
|
|
2019
|
-
|
|
2021
|
+
changed.add(consumer);
|
|
2022
|
+
content.add(consumer);
|
|
2020
2023
|
}
|
|
2021
2024
|
}
|
|
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
|
-
|
|
2025
|
+
if (current === undefined) continue;
|
|
2026
|
+
const existing = entry.projection.slot(worldId, current);
|
|
2027
|
+
const membershipChanged =
|
|
2028
|
+
batch.membershipChanged &&
|
|
2029
|
+
(existing === undefined || sourceMembershipChanged(world, existing));
|
|
2030
|
+
let contentChanged = membershipChanged;
|
|
2031
|
+
for (const component of contentComponents) {
|
|
2032
|
+
if (source.projection.changed(current, component)) contentChanged = true;
|
|
2033
|
+
}
|
|
2034
|
+
if (
|
|
2035
|
+
(contentChanged || (instancesChanged && source.projection.changed(current, Instances))) &&
|
|
2036
|
+
isRenderableMember(world, current)
|
|
2037
|
+
) {
|
|
2038
|
+
changed.add(current);
|
|
2039
|
+
if (contentChanged) content.add(current);
|
|
2040
|
+
}
|
|
2041
|
+
if (
|
|
2042
|
+
version.structureEpoch !== read.version.structureEpoch ||
|
|
2043
|
+
source.projection.changed(current, ChildOf) ||
|
|
2044
|
+
source.projection.changed(current, Visibility)
|
|
2045
|
+
) {
|
|
2046
|
+
if (!dependencyVisited.has(current)) {
|
|
2047
|
+
const pending = [current];
|
|
2048
|
+
while (pending.length > 0) {
|
|
2049
|
+
const dependent = pending.pop();
|
|
2050
|
+
if (dependent === undefined || dependencyVisited.has(dependent)) continue;
|
|
2051
|
+
dependencyVisited.add(dependent);
|
|
2052
|
+
const children = world.hasComponent(dependent, Children)
|
|
2053
|
+
? world.get(dependent, Children)
|
|
2054
|
+
: undefined;
|
|
2055
|
+
if (children?.ok)
|
|
2056
|
+
for (const child of children.value.entities) pending.push(child as EntityHandle);
|
|
2057
|
+
if (!isRenderableMember(world, dependent)) continue;
|
|
2058
|
+
changed.add(dependent);
|
|
2059
|
+
content.add(dependent);
|
|
2054
2060
|
}
|
|
2055
2061
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
for (const handle of runtimeAssets) {
|
|
2065
|
+
this.options.onRuntimeAssetChange?.(worldId, handle);
|
|
2066
|
+
entry.projection.addSharedRefConsumers(worldId, handle, content);
|
|
2067
|
+
}
|
|
2068
|
+
for (const entity of content) changed.add(entity);
|
|
2069
|
+
const query = entry.transformQueries[worldId];
|
|
2070
|
+
if (query !== undefined) {
|
|
2071
|
+
for (const span of query.spans().unwrap()) {
|
|
2072
|
+
const matrices = span.get(GlobalTransform).world;
|
|
2073
|
+
if (!(matrices instanceof Float32Array))
|
|
2074
|
+
throw new Error('GlobalTransform projection must expose a numeric column.');
|
|
2075
|
+
transformSpans.push({ worldId, entities: span.entities, worlds: matrices });
|
|
2076
|
+
if (entry.skinConsumersByJoint.size > 0) {
|
|
2077
|
+
for (const entity of span.entities) {
|
|
2078
|
+
for (const consumer of entry.skinConsumersByJoint.get(
|
|
2079
|
+
skinJointKey(worldId, entity),
|
|
2080
|
+
) ?? []) {
|
|
2081
|
+
changed.add(consumer);
|
|
2082
|
+
content.add(consumer);
|
|
2083
|
+
}
|
|
2071
2084
|
}
|
|
2072
2085
|
}
|
|
2073
2086
|
}
|
|
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
2087
|
}
|
|
2081
2088
|
}
|
|
2082
2089
|
|
|
@@ -2089,6 +2096,8 @@ export class PersistentRenderScene {
|
|
|
2089
2096
|
for (const entityKey of changedEntitiesByWorld[worldId] ?? []) pending.add(entityKey);
|
|
2090
2097
|
}
|
|
2091
2098
|
|
|
2099
|
+
const resourceFrame = buildCandidateFrame('none');
|
|
2100
|
+
for (const batch of sourceBatches) batch.validate();
|
|
2092
2101
|
let changedDelta: RenderSceneApplyResult | undefined;
|
|
2093
2102
|
const hasChangedEntities = changedEntitiesByWorld.some((entities) => entities.size > 0);
|
|
2094
2103
|
if (hasChangedEntities || removedSlots.length > 0 || transformSpans.length > 0) {
|
|
@@ -2103,9 +2112,6 @@ export class PersistentRenderScene {
|
|
|
2103
2112
|
}
|
|
2104
2113
|
for (const slot of removedSlots) {
|
|
2105
2114
|
operations.push({ kind: 'remove', worldId: slot.worldId, entityKey: slot.entityKey });
|
|
2106
|
-
if (slot.snapshot.skinJointEntities !== undefined) {
|
|
2107
|
-
removeSkinConsumer(entry.skinConsumersByJoint, slot.snapshot);
|
|
2108
|
-
}
|
|
2109
2115
|
for (
|
|
2110
2116
|
let materialIndex = 0;
|
|
2111
2117
|
materialIndex < slot.snapshot.materials.length;
|
|
@@ -2162,7 +2168,23 @@ export class PersistentRenderScene {
|
|
|
2162
2168
|
});
|
|
2163
2169
|
publishedEntitiesByWorld[snapshot.worldId]?.add(snapshot.entityKey);
|
|
2164
2170
|
}
|
|
2171
|
+
for (const batch of sourceBatches) batch.validate();
|
|
2165
2172
|
changedDelta = entry.projection.apply(operations, transformSpans);
|
|
2173
|
+
for (const slot of changedDelta.removedSlots) {
|
|
2174
|
+
const world = worlds[slot.worldId];
|
|
2175
|
+
if (world !== undefined) this.options.instanceCollections?.release(world, slot.entityKey);
|
|
2176
|
+
}
|
|
2177
|
+
for (const snapshot of partial?.renderables ?? []) {
|
|
2178
|
+
const world = worlds[snapshot.worldId];
|
|
2179
|
+
if (world === undefined) continue;
|
|
2180
|
+
if (snapshot.instances === undefined)
|
|
2181
|
+
this.options.instanceCollections?.release(world, snapshot.entityKey);
|
|
2182
|
+
else
|
|
2183
|
+
this.options.instanceCollections?.accept(world, snapshot.entityKey, snapshot.instances);
|
|
2184
|
+
}
|
|
2185
|
+
for (const slot of removedSlots)
|
|
2186
|
+
if (slot.snapshot.skinJointEntities !== undefined)
|
|
2187
|
+
removeSkinConsumer(entry.skinConsumersByJoint, slot.snapshot);
|
|
2166
2188
|
const publishedSkinKeys = new Set<string>();
|
|
2167
2189
|
for (const snapshot of partial?.renderables ?? []) {
|
|
2168
2190
|
publishedSkinKeys.add(`${snapshot.worldId}:${snapshot.entityKey}`);
|
|
@@ -2198,7 +2220,7 @@ export class PersistentRenderScene {
|
|
|
2198
2220
|
return (
|
|
2199
2221
|
worldId !== undefined &&
|
|
2200
2222
|
!changedEntitiesByWorld[worldId]?.has(report.entity) &&
|
|
2201
|
-
|
|
2223
|
+
isRenderableMember(report.world, report.entity)
|
|
2202
2224
|
);
|
|
2203
2225
|
}),
|
|
2204
2226
|
...(partial?.hiddenEntityReports ?? []),
|
|
@@ -2227,8 +2249,9 @@ export class PersistentRenderScene {
|
|
|
2227
2249
|
continue;
|
|
2228
2250
|
}
|
|
2229
2251
|
if (slot === undefined) {
|
|
2230
|
-
const
|
|
2231
|
-
if (
|
|
2252
|
+
const world = worlds[worldId];
|
|
2253
|
+
if (world !== undefined && !isRenderableMember(world, entityKey))
|
|
2254
|
+
pending?.delete(entityKey);
|
|
2232
2255
|
continue;
|
|
2233
2256
|
}
|
|
2234
2257
|
// The producer did not publish this requested identity. Keep the
|
|
@@ -2279,9 +2302,43 @@ export class PersistentRenderScene {
|
|
|
2279
2302
|
this.noChangeFrames += 1;
|
|
2280
2303
|
this.syncGpuOwner(entry.token, entry.projection);
|
|
2281
2304
|
}
|
|
2282
|
-
const result = this.deriveFramePlan(entry,
|
|
2305
|
+
const result = this.deriveFramePlan(entry, resourceFrame);
|
|
2306
|
+
for (let worldId = 0; worldId < sourceBatches.length; worldId++) {
|
|
2307
|
+
const batch = sourceBatches[worldId];
|
|
2308
|
+
const source = entry.sourceStates[worldId];
|
|
2309
|
+
if (batch === undefined || source === undefined) continue;
|
|
2310
|
+
batch.accept();
|
|
2311
|
+
if (
|
|
2312
|
+
!batch.membershipChanged &&
|
|
2313
|
+
!batch.changedComponents.includes(RuntimeMaterialValue) &&
|
|
2314
|
+
!batch.changedComponents.includes(RuntimeMeshVertices)
|
|
2315
|
+
)
|
|
2316
|
+
continue;
|
|
2317
|
+
for (const index of batch.indices) {
|
|
2318
|
+
const entity = source.projection.entity(index);
|
|
2319
|
+
if (entity === undefined) {
|
|
2320
|
+
source.entities.delete(index);
|
|
2321
|
+
source.contentHandles.delete(index);
|
|
2322
|
+
} else {
|
|
2323
|
+
source.entities.set(index, entity);
|
|
2324
|
+
const handles: number[] = [];
|
|
2325
|
+
const world = worlds[worldId];
|
|
2326
|
+
if (world !== undefined) {
|
|
2327
|
+
const material = world.hasComponent(entity, RuntimeMaterialValue)
|
|
2328
|
+
? world.get(entity, RuntimeMaterialValue)
|
|
2329
|
+
: undefined;
|
|
2330
|
+
const mesh = world.hasComponent(entity, RuntimeMeshVertices)
|
|
2331
|
+
? world.get(entity, RuntimeMeshVertices)
|
|
2332
|
+
: undefined;
|
|
2333
|
+
if (material?.ok) handles.push(Number(material.value.asset));
|
|
2334
|
+
if (mesh?.ok) handles.push(Number(mesh.value.asset));
|
|
2335
|
+
}
|
|
2336
|
+
if (handles.length === 0) source.contentHandles.delete(index);
|
|
2337
|
+
else source.contentHandles.set(index, handles);
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2283
2341
|
entry.catalogEpoch = catalogEpoch;
|
|
2284
|
-
entry.instanceEpoch = instanceEpoch;
|
|
2285
2342
|
for (let worldId = 0; worldId < nextReadVersions.length; worldId += 1) {
|
|
2286
2343
|
const version = nextReadVersions[worldId];
|
|
2287
2344
|
if (version !== undefined) entry.readVersions[worldId] = version;
|
|
@@ -2328,11 +2385,13 @@ export class PersistentRenderScene {
|
|
|
2328
2385
|
this.stableSlotByEntity.clear();
|
|
2329
2386
|
}
|
|
2330
2387
|
if (this.gpuOwner !== world && this.gpuOwner !== detachedComposition?.token) return;
|
|
2331
|
-
|
|
2332
|
-
|
|
2388
|
+
// The GPU Scene is renderer-owned. A frame graph recorded for the current
|
|
2389
|
+
// device may retain its table bindings after a World detaches, while the
|
|
2390
|
+
// next attached composition can rebuild the same tables in place. Keep
|
|
2391
|
+
// that single scene resident until device replacement or renderer
|
|
2392
|
+
// disposal; retiring it here lets a reused graph submit destroyed buffers.
|
|
2333
2393
|
this.gpuOwner = undefined;
|
|
2334
|
-
this.
|
|
2335
|
-
this.gpuStatus = 'inactive';
|
|
2394
|
+
this.gpuStatus = this.gpuScene === undefined ? 'inactive' : 'resident';
|
|
2336
2395
|
}
|
|
2337
2396
|
|
|
2338
2397
|
/** Drop only device-owned tables; the CPU projection remains the recovery authority. */
|
|
@@ -2398,6 +2457,9 @@ export class PersistentRenderScene {
|
|
|
2398
2457
|
scene,
|
|
2399
2458
|
plan: composition.topology.plan(),
|
|
2400
2459
|
slots,
|
|
2460
|
+
worldKeys: composition.worldKeys,
|
|
2461
|
+
worldIdentities: composition.worlds.map((world) => world.identity),
|
|
2462
|
+
probeBlend: composition.probeProjection.recordBufferProjection(),
|
|
2401
2463
|
});
|
|
2402
2464
|
let published = false;
|
|
2403
2465
|
let released = false;
|
|
@@ -2569,11 +2631,13 @@ export class PersistentRenderScene {
|
|
|
2569
2631
|
plan: entry.topology.plan(),
|
|
2570
2632
|
slots: entry.projection.slotsSnapshot(),
|
|
2571
2633
|
worldKeys: entry.worldKeys,
|
|
2634
|
+
worldIdentities: entry.worlds.map((world) => world.identity),
|
|
2572
2635
|
structureMetrics: {
|
|
2573
2636
|
worldEntitiesScanned: this.worldEntitiesScanned,
|
|
2574
2637
|
sceneTableUploadBytes: this.sceneTableUploadBytes,
|
|
2575
2638
|
paletteUploadBytes: 0,
|
|
2576
2639
|
},
|
|
2640
|
+
probeBlend: entry.probeProjection.recordBufferProjection(),
|
|
2577
2641
|
};
|
|
2578
2642
|
}
|
|
2579
2643
|
|
|
@@ -2647,7 +2711,12 @@ export class PersistentRenderScene {
|
|
|
2647
2711
|
preserveVisibilityOnReorder = false,
|
|
2648
2712
|
): ExtractedFrame {
|
|
2649
2713
|
const previousEntry = this.composition;
|
|
2650
|
-
const
|
|
2714
|
+
const sourceStates = worlds.map((world) => createRenderSourceState(world));
|
|
2715
|
+
const candidateFrame = buildCandidateFrame({
|
|
2716
|
+
kind: 'partial',
|
|
2717
|
+
entitiesByWorld: sourceStates.map((source) => new Set(source.entities.values())),
|
|
2718
|
+
});
|
|
2719
|
+
for (const source of sourceStates) source.batch.validate();
|
|
2651
2720
|
this.temporalCapture = undefined;
|
|
2652
2721
|
this.worldEntitiesScanned = candidateFrame.renderables.length;
|
|
2653
2722
|
const worldKeys = this.visibilityWorldKeysFor(worlds);
|
|
@@ -2675,38 +2744,18 @@ export class PersistentRenderScene {
|
|
|
2675
2744
|
this.invalidateActiveEntityRevision();
|
|
2676
2745
|
}
|
|
2677
2746
|
}
|
|
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
|
-
};
|
|
2747
|
+
const stableCandidateFrame = candidateFrame;
|
|
2748
|
+
const renderables = candidateFrame.renderables;
|
|
2704
2749
|
const projection = previousEntry?.projection ?? new RenderScene();
|
|
2705
2750
|
if (previousEntry !== undefined) {
|
|
2706
|
-
projection.remapWorlds(
|
|
2751
|
+
projection.remapWorlds(
|
|
2752
|
+
previousEntry.worlds.map((world) =>
|
|
2753
|
+
(worlds as readonly RenderResourceScope[]).indexOf(world),
|
|
2754
|
+
),
|
|
2755
|
+
);
|
|
2707
2756
|
}
|
|
2708
2757
|
const desired = new Set(
|
|
2709
|
-
|
|
2758
|
+
renderables.map((snapshot) => identityKey(snapshot.worldId, snapshot.entityKey)),
|
|
2710
2759
|
);
|
|
2711
2760
|
const operations: RenderSceneOperation[] = [];
|
|
2712
2761
|
for (const slot of projection.slotsSnapshot()) {
|
|
@@ -2714,7 +2763,7 @@ export class PersistentRenderScene {
|
|
|
2714
2763
|
operations.push({ kind: 'remove', worldId: slot.worldId, entityKey: slot.entityKey });
|
|
2715
2764
|
}
|
|
2716
2765
|
}
|
|
2717
|
-
for (const snapshot of
|
|
2766
|
+
for (const snapshot of renderables) {
|
|
2718
2767
|
operations.push({
|
|
2719
2768
|
kind: 'update',
|
|
2720
2769
|
worldId: snapshot.worldId,
|
|
@@ -2723,6 +2772,22 @@ export class PersistentRenderScene {
|
|
|
2723
2772
|
});
|
|
2724
2773
|
}
|
|
2725
2774
|
const delta = projection.apply(operations);
|
|
2775
|
+
for (const snapshot of renderables) {
|
|
2776
|
+
const world = worlds[snapshot.worldId];
|
|
2777
|
+
if (world !== undefined && snapshot.instances !== undefined)
|
|
2778
|
+
this.options.instanceCollections?.accept(world, snapshot.entityKey, snapshot.instances);
|
|
2779
|
+
}
|
|
2780
|
+
this.options.instanceCollections?.retain(
|
|
2781
|
+
new Set(
|
|
2782
|
+
projection
|
|
2783
|
+
.slotsSnapshot()
|
|
2784
|
+
.flatMap((slot) =>
|
|
2785
|
+
slot.snapshot.instances?.collectionId === undefined
|
|
2786
|
+
? []
|
|
2787
|
+
: [slot.snapshot.instances.collectionId],
|
|
2788
|
+
),
|
|
2789
|
+
),
|
|
2790
|
+
);
|
|
2726
2791
|
this.stableSlotByEntity.clear();
|
|
2727
2792
|
for (const slot of projection.slotsSnapshot()) {
|
|
2728
2793
|
const stableWorld = worldKeys[slot.worldId] ?? slot.worldId;
|
|
@@ -2757,10 +2822,7 @@ export class PersistentRenderScene {
|
|
|
2757
2822
|
leases === undefined || leases.length !== worlds.length
|
|
2758
2823
|
? []
|
|
2759
2824
|
: worlds.map(createGlobalTransformChangeQuery),
|
|
2760
|
-
|
|
2761
|
-
leases === undefined || leases.length !== worlds.length
|
|
2762
|
-
? []
|
|
2763
|
-
: worlds.map(createRenderChangeQueries),
|
|
2825
|
+
sourceStates,
|
|
2764
2826
|
dispatchBySlot: dispatchEntriesBySlot(stableCandidateFrame, projection),
|
|
2765
2827
|
dispatchRevision: 0,
|
|
2766
2828
|
dispatchCache: undefined,
|
|
@@ -2768,8 +2830,8 @@ export class PersistentRenderScene {
|
|
|
2768
2830
|
pendingRenderableEntitiesByWorld: worlds.map(() => new Set<number>()),
|
|
2769
2831
|
unavailableSlots: new Set<number>(),
|
|
2770
2832
|
catalogEpoch,
|
|
2771
|
-
instanceEpoch: this.options.instanceCollections?.epoch ?? 0,
|
|
2772
2833
|
probeProjection: new ProbeBlendSceneProjection(),
|
|
2834
|
+
probeObjects: undefined,
|
|
2773
2835
|
temporalDemanded: frameDemandsTemporal(candidateFrame),
|
|
2774
2836
|
gpuDrivenSceneRequired: true,
|
|
2775
2837
|
};
|
|
@@ -2804,6 +2866,7 @@ export class PersistentRenderScene {
|
|
|
2804
2866
|
? projection.cullingWorldBounds(snapshot)
|
|
2805
2867
|
: projection.cullingWorldBoundsAt(slot);
|
|
2806
2868
|
});
|
|
2869
|
+
for (const source of sourceStates) source.batch.accept();
|
|
2807
2870
|
this.frameEpoch += 1;
|
|
2808
2871
|
this.visibilityFacetFrame = undefined;
|
|
2809
2872
|
this.visibilityProjectionCache = undefined;
|
|
@@ -2826,9 +2889,8 @@ export class PersistentRenderScene {
|
|
|
2826
2889
|
*/
|
|
2827
2890
|
private deriveFramePlan(
|
|
2828
2891
|
entry: PersistentCompositionEntry,
|
|
2829
|
-
|
|
2892
|
+
resourceFrame: ExtractedFrame,
|
|
2830
2893
|
): ExtractedFrame {
|
|
2831
|
-
const resourceFrame = buildCandidateFrame('none');
|
|
2832
2894
|
const cachedDispatch = entry.dispatchCache;
|
|
2833
2895
|
const dispatch =
|
|
2834
2896
|
cachedDispatch?.revision === entry.dispatchRevision
|
|
@@ -2840,7 +2902,10 @@ export class PersistentRenderScene {
|
|
|
2840
2902
|
const candidateFrame: ExtractedFrame = {
|
|
2841
2903
|
...resourceFrame,
|
|
2842
2904
|
hiddenEntityReports: entry.hiddenEntityReports,
|
|
2843
|
-
visibilityStats:
|
|
2905
|
+
visibilityStats:
|
|
2906
|
+
entry.sourceStates.length === 0
|
|
2907
|
+
? resourceFrame.visibilityStats
|
|
2908
|
+
: { explicitlyHidden: entry.hiddenEntityReports.length },
|
|
2844
2909
|
dispatch,
|
|
2845
2910
|
};
|
|
2846
2911
|
entry.temporalDemanded = frameDemandsTemporal(candidateFrame);
|
|
@@ -2938,27 +3003,41 @@ export class PersistentRenderScene {
|
|
|
2938
3003
|
] as [number, number, number],
|
|
2939
3004
|
};
|
|
2940
3005
|
const probes = frame.lightProbes ?? [];
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
3006
|
+
const revision = entry.projection.revisionValue();
|
|
3007
|
+
if (entry.probeObjects?.revision !== revision) {
|
|
3008
|
+
const slots = entry.projection.slotsSnapshot();
|
|
3009
|
+
const value = Object.freeze(
|
|
3010
|
+
slots.map((slot) =>
|
|
3011
|
+
Object.freeze({
|
|
3012
|
+
objectKey: slot.slot,
|
|
3013
|
+
generation: slot.generation,
|
|
3014
|
+
position: [
|
|
3015
|
+
slot.snapshot.transform.world[12] ?? 0,
|
|
3016
|
+
slot.snapshot.transform.world[13] ?? 0,
|
|
3017
|
+
slot.snapshot.transform.world[14] ?? 0,
|
|
3018
|
+
] as const,
|
|
3019
|
+
}),
|
|
3020
|
+
),
|
|
3021
|
+
);
|
|
3022
|
+
entry.probeObjects = {
|
|
3023
|
+
revision,
|
|
3024
|
+
value,
|
|
3025
|
+
surfaceValue: Object.freeze(
|
|
3026
|
+
value.filter((_object, index) =>
|
|
3027
|
+
slots[index]?.snapshot.materials.some(
|
|
3028
|
+
(material) => material.surfaceModel === 'single-layer-medium',
|
|
3029
|
+
),
|
|
3030
|
+
),
|
|
3031
|
+
),
|
|
3032
|
+
};
|
|
2948
3033
|
}
|
|
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
|
-
}));
|
|
3034
|
+
const surfaceOnly = probes.length === 0;
|
|
2958
3035
|
entry.probeProjection.apply({
|
|
2959
|
-
objects,
|
|
3036
|
+
objects: surfaceOnly ? entry.probeObjects.surfaceValue : entry.probeObjects.value,
|
|
2960
3037
|
probes,
|
|
2961
3038
|
sky,
|
|
3039
|
+
worldRevision: revision,
|
|
3040
|
+
...(surfaceOnly ? { retainSkyResidualRecords: true } : {}),
|
|
2962
3041
|
});
|
|
2963
3042
|
}
|
|
2964
3043
|
|