@forgeax/engine-render 0.1.32 → 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 +1374 -142
- package/dist/assembly/analytic-fog-registration.d.ts +3 -0
- package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
- 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/fxaa-registration.d.ts +4 -0
- package/dist/assembly/fxaa-registration.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +3 -3
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/lod-observation.d.ts +4 -0
- package/dist/assembly/lod-observation.d.ts.map +1 -0
- 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/motion-blur-registration.d.ts +3 -0
- package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
- 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/temporal-post-process-prewarm.d.ts +13 -0
- package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
- 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-contract.d.ts +4 -3
- package/dist/assembly/webgpu-ready-contract.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 +2 -2
- 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/bloom-admission.d.ts +13 -0
- package/dist/bloom-admission.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-JCIRYQ4V.mjs → chunk-HEB564WF.mjs} +10 -4
- package/dist/chunk-HEB564WF.mjs.map +1 -0
- package/dist/{chunk-JRIPCMYC.mjs → chunk-MKDIT2EM.mjs} +1584 -375
- package/dist/chunk-MKDIT2EM.mjs.map +1 -0
- package/dist/{chunk-S665NJNF.mjs → chunk-OCDLEI6I.mjs} +3 -3
- package/dist/{chunk-S665NJNF.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-DRR7D3KX.mjs → chunk-SHFUFJ5N.mjs} +192 -18
- package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
- package/dist/{chunk-4NNZQCL3.mjs → chunk-UI5SFODX.mjs} +223 -277
- package/dist/chunk-UI5SFODX.mjs.map +1 -0
- package/dist/{chunk-GWCEMDVR.mjs → chunk-UINHLCZA.mjs} +787 -80
- package/dist/chunk-UINHLCZA.mjs.map +1 -0
- package/dist/{chunk-6TFBXLRJ.mjs → chunk-WEX45HKH.mjs} +222 -337
- 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/atmosphere.d.ts +2 -0
- package/dist/components/atmosphere.d.ts.map +1 -1
- package/dist/components/barrel-distortion.d.ts +13 -0
- package/dist/components/barrel-distortion.d.ts.map +1 -0
- package/dist/components/camera.d.ts +20 -4
- package/dist/components/camera.d.ts.map +1 -1
- 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/components/mesh-filter.d.ts +6 -5
- package/dist/components/mesh-filter.d.ts.map +1 -1
- package/dist/components/motion-blur.d.ts +1 -0
- package/dist/components/motion-blur.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 +9751 -3528
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +6 -0
- 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/environment/analytic-fog.d.ts +6 -0
- package/dist/environment/analytic-fog.d.ts.map +1 -0
- package/dist/errors/cloud.d.ts +59 -0
- package/dist/errors/cloud.d.ts.map +1 -0
- package/dist/errors/render.d.ts +23 -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 +12 -1
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/environment.d.ts +2 -0
- package/dist/extract/environment.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 +17 -0
- package/dist/features/error-reporting.d.ts.map +1 -0
- package/dist/features/host.d.ts +15 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-feature.d.ts +20 -2
- package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
- package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
- package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
- package/dist/features/plan.d.ts +15 -4
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +9 -5
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/render-graph-compute.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 +7 -0
- 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 +50 -4
- 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 +35 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +11 -1
- 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 +31 -8
- 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 +178 -3
- 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 +49 -94
- 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 +28 -19
- 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/pipeline-spec.d.ts +2 -2
- 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 +40 -3
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +14 -62
- 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/mesh-ssbo.d.ts +6 -5
- package/dist/record/mesh-ssbo.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 +34 -31
- 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 +6 -4
- 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 +66 -8
- 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 +106 -3
- 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 +24 -10
- 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 +26 -15
- 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 +14 -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/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +7 -0
- package/dist/temporal/frame.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/temporal/view.d.ts +6 -1
- package/dist/temporal/view.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 +24 -9
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +9 -5
- 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/dist/volume/temporal.d.ts +3 -1
- package/dist/volume/temporal.d.ts.map +1 -1
- package/package.json +22 -21
- package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
- package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
- 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__/bloom-exact-zero.unit.test.ts +112 -18
- package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
- 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__/dynamic-resolution-plugin.integration.test.ts +20 -0
- package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
- package/src/__tests__/environment-selection.unit.test.ts +12 -0
- package/src/__tests__/factory-contract.integration.test.ts +626 -113
- package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
- package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
- package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
- 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-indirect-raster-evidence.ts +2 -1
- 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 +7 -6
- package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +103 -4
- 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-resource-store-stride.unit.test.ts +12 -0
- package/src/__tests__/gpu-scene.unit.test.ts +210 -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 +105 -238
- 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__/mesh-submission-lifetime.unit.test.ts +31 -0
- 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 +589 -0
- 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-gpu-driven-pbr.integration.test.ts +21 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
- package/src/__tests__/probe-bindings.unit.test.ts +582 -1
- package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
- package/src/__tests__/public-surface.test-d.ts +8 -0
- 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 +9 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
- package/src/__tests__/render-feature-error-reporting.unit.test.ts +44 -0
- 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-feature-stage-fault-recovery.unit.test.ts +23 -0
- 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 +37 -6
- 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 +33 -11
- package/src/__tests__/resource-allocation.unit.test.ts +123 -0
- package/src/__tests__/shader-manifest-fixture.ts +4 -4
- 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 +17 -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-lighting-write.unit.test.ts +2 -1
- 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.dawn.test.ts +1 -1
- package/src/__tests__/standard-pipeline.integration.test.ts +200 -9
- 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__/temporal-reset-matrix.unit.test.ts +10 -0
- package/src/__tests__/temporal-view.unit.test.ts +2 -1
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
- 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 +7 -3
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +189 -15
- 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 +558 -68
- package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +23 -5
- package/src/assembly/analytic-fog-registration.ts +14 -0
- 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/fxaa-registration.ts +17 -0
- package/src/assembly/host-contract.ts +3 -3
- package/src/assembly/lod-observation.ts +12 -0
- 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/motion-blur-registration.ts +17 -0
- 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 +6 -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 +40 -0
- package/src/assembly/webgpu-pbr-ready.ts +9 -1
- package/src/assembly/webgpu-ready-contract.ts +8 -3
- package/src/assembly/webgpu-ready-per-pass.ts +104 -0
- package/src/assembly/webgpu-ready.ts +296 -306
- 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 +228 -281
- package/src/assembly/webgpu-vertex-layouts.ts +1 -1
- package/src/barrel-distortion.ts +247 -0
- package/src/bloom-admission.ts +21 -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/__tests__/motion-blur.unit.test.ts +1 -0
- package/src/components/atmosphere.ts +4 -0
- package/src/components/barrel-distortion.ts +46 -0
- package/src/components/camera.ts +66 -10
- 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/mesh-filter.ts +11 -9
- package/src/components/motion-blur.ts +1 -0
- package/src/components/sprite-instances.ts +1 -1
- package/src/construct-renderer.ts +1 -1
- package/src/device/gpu-residency.ts +56 -12
- package/src/dynamic-geometry.ts +12 -1
- package/src/environment/analytic-fog.ts +44 -0
- package/src/environment/background.ts +2 -2
- package/src/errors/cloud.ts +103 -0
- package/src/errors/render.ts +58 -8
- package/src/examples/single-layer-medium-surface.ts +59 -0
- package/src/extract/camera.ts +35 -8
- package/src/extract/contracts.ts +12 -0
- package/src/extract/environment.ts +4 -0
- package/src/features/barrel-distortion.ts +172 -0
- package/src/features/error-reporting.ts +98 -0
- package/src/features/host.ts +138 -24
- package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
- package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
- package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
- package/src/features/motion-blur/motion-blur-params.ts +70 -2
- package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
- package/src/features/plan.ts +33 -8
- package/src/features/prepared-gpu-work.ts +86 -35
- package/src/features/render-graph-compute.ts +13 -5
- package/src/features/render-graph-contribution.ts +11 -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 +35 -32
- package/src/gpu-driven/prepared-draw.ts +27 -14
- package/src/gpu-driven/production-raster-material.ts +1894 -0
- package/src/gpu-driven/production-raster.ts +904 -787
- 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 +181 -10
- package/src/gpu-scene.ts +259 -101
- package/src/hdrp-buffers.ts +4 -3
- package/src/ibl/skylight-bind-group.ts +49 -7
- package/src/index.ts +228 -9
- package/src/inspection-types.ts +222 -2
- package/src/instance-buffer-cache.ts +4 -4
- package/src/instances.ts +151 -492
- 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 +397 -102
- package/src/pipeline-builder.ts +1 -1
- package/src/pipeline-spec.ts +5 -5
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
- package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
- 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 +3 -2
- 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 +44 -4
- package/src/record/frame-targets.ts +10 -6
- package/src/record/frame.ts +373 -1099
- package/src/record/gpu-draw-receipts.ts +38 -0
- package/src/record/gpu-timing.ts +48 -5
- package/src/record/main-pass-geometry.ts +281 -83
- package/src/record/main-pass-material.ts +66 -4
- package/src/record/main-pass-sprite-draws.ts +13 -66
- package/src/record/main-pass.ts +156 -20
- package/src/record/mesh-ssbo.ts +43 -6
- 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 +51 -31
- package/src/record/shadow-pass.ts +36 -2
- package/src/record/skybox-post-pass.ts +150 -200
- package/src/record/typed-frame-graph.ts +824 -44
- package/src/record/view-ubo.ts +26 -3
- package/src/record/volume-params.ts +225 -0
- package/src/recovery/render-system-candidate.ts +257 -52
- package/src/reflection/record-owner.ts +7 -3
- package/src/render-contract.ts +71 -8
- package/src/render-graph-primitives.ts +7 -1
- package/src/render-pipeline.ts +136 -1
- package/src/render-system-extract-tail.ts +72 -60
- package/src/render-system-extract.ts +117 -87
- 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 +601 -482
- package/src/scene/probe-blend.ts +96 -4
- package/src/scene/render-scene.ts +431 -281
- 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/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
- package/src/temporal/frame-coordinator.ts +8 -1
- package/src/temporal/frame.ts +20 -0
- 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/temporal/view.ts +13 -2
- 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 +191 -50
- package/src/volume/component.ts +10 -10
- package/src/volume/extract.ts +11 -5
- package/src/volume/inspection.ts +3 -0
- package/src/volume/passes.ts +95 -8
- package/src/volume/resources.ts +2 -1
- package/src/volume/temporal.ts +11 -0
- package/dist/chunk-4NNZQCL3.mjs.map +0 -1
- package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
- package/dist/chunk-DRR7D3KX.mjs.map +0 -1
- package/dist/chunk-GWCEMDVR.mjs.map +0 -1
- package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
- package/dist/chunk-JRIPCMYC.mjs.map +0 -1
- package/dist/chunk-LULCA3OF.mjs +0 -1713
- package/dist/chunk-LULCA3OF.mjs.map +0 -1
- package/dist/chunk-PA5DRJNI.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 {
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from '../components';
|
|
27
27
|
import type { DeviceScope, LifecycleResourceSpec } from '../device/device-scope';
|
|
28
28
|
import { gpuDrivenShadowDrawKey } from '../extract/gpu-driven';
|
|
29
|
+
import { motionBlurTemporalDemand } from '../features/motion-blur/motion-blur-params';
|
|
29
30
|
import {
|
|
30
31
|
BatchTopology,
|
|
31
32
|
type BatchTopologyInspection,
|
|
@@ -36,7 +37,7 @@ import type {
|
|
|
36
37
|
GpuDrivenStructureMetrics,
|
|
37
38
|
PersistentRenderSceneInspection,
|
|
38
39
|
} from '../inspection-types';
|
|
39
|
-
import type {
|
|
40
|
+
import type { InstanceProjectionStore } from '../instances';
|
|
40
41
|
import { fingerprintNumericArray, InstanceBoundsCache } from '../instances-derived-bounds';
|
|
41
42
|
import type { PointsLinesInspection } from '../points-lines/inspection';
|
|
42
43
|
import type { PointsLinesRetainedSnapshot } from '../points-lines/snapshot';
|
|
@@ -61,7 +62,11 @@ import {
|
|
|
61
62
|
type TransmissionDemand,
|
|
62
63
|
type TransmissionDemandOperation,
|
|
63
64
|
} from '../transmission/projection';
|
|
64
|
-
import {
|
|
65
|
+
import {
|
|
66
|
+
type ProbeBlendBufferProjection,
|
|
67
|
+
ProbeBlendSceneProjection,
|
|
68
|
+
type ProbeSceneObjectInput,
|
|
69
|
+
} from './probe-blend';
|
|
65
70
|
import type {
|
|
66
71
|
RenderSceneApplyResult,
|
|
67
72
|
RenderSceneBounds,
|
|
@@ -115,6 +120,41 @@ interface WorldTransformSpan {
|
|
|
115
120
|
|
|
116
121
|
type GlobalTransformChangeQuery = Query<readonly [typeof GlobalTransform]>;
|
|
117
122
|
|
|
123
|
+
function sameInstanceIdentitySet(
|
|
124
|
+
current: Uint32Array | undefined,
|
|
125
|
+
previous: Uint32Array | undefined,
|
|
126
|
+
): boolean {
|
|
127
|
+
// An instanced producer without generation tokens cannot prove that a
|
|
128
|
+
// compacted/reordered row is the same logical object. Keep that legacy
|
|
129
|
+
// snapshot conservative: the record stage will seed its previous matrix
|
|
130
|
+
// instead of borrowing a velocity from an unknown ordinal.
|
|
131
|
+
if (current === undefined || previous === undefined) return false;
|
|
132
|
+
const currentSet = new Set(current);
|
|
133
|
+
const previousSet = new Set(previous);
|
|
134
|
+
if (
|
|
135
|
+
currentSet.size !== current.length ||
|
|
136
|
+
previousSet.size !== previous.length ||
|
|
137
|
+
current.some((identity) => identity === 0) ||
|
|
138
|
+
previous.some((identity) => identity === 0)
|
|
139
|
+
) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
if (current.length === previous.length) {
|
|
143
|
+
let sameOrder = true;
|
|
144
|
+
for (let index = 0; index < current.length; index += 1) {
|
|
145
|
+
if (current[index] !== previous[index]) {
|
|
146
|
+
sameOrder = false;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (sameOrder) return true;
|
|
151
|
+
}
|
|
152
|
+
// Reorder and retirement are valid when every current token is unique and
|
|
153
|
+
// survives. The set is built only on the topology-change path; steady pose
|
|
154
|
+
// updates stay on the linear same-order check and do not allocate.
|
|
155
|
+
return current.every((identity) => previousSet.has(identity));
|
|
156
|
+
}
|
|
157
|
+
|
|
118
158
|
/** The normal extract request used by the persistent scene owner. */
|
|
119
159
|
export type PersistentRenderCandidateRequest =
|
|
120
160
|
| 'full'
|
|
@@ -202,6 +242,9 @@ function ownSnapshot(snapshot: RenderableSnapshot): RenderableSnapshot {
|
|
|
202
242
|
instances: {
|
|
203
243
|
...snapshot.instances,
|
|
204
244
|
transforms: new Float32Array(snapshot.instances.transforms),
|
|
245
|
+
...(snapshot.instances.generations === undefined
|
|
246
|
+
? {}
|
|
247
|
+
: { generations: new Uint32Array(snapshot.instances.generations) }),
|
|
205
248
|
},
|
|
206
249
|
}),
|
|
207
250
|
...(snapshot.spriteInstances === undefined
|
|
@@ -363,16 +406,33 @@ export class RenderScene {
|
|
|
363
406
|
return this.emptyResult();
|
|
364
407
|
}
|
|
365
408
|
|
|
366
|
-
|
|
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;
|
|
367
413
|
if (
|
|
368
|
-
operation.kind === 'update' &&
|
|
369
414
|
operation.snapshot !== undefined &&
|
|
370
415
|
(operation.worldId !== operation.snapshot.worldId ||
|
|
371
416
|
operation.entityKey !== operation.snapshot.entityKey)
|
|
372
417
|
) {
|
|
373
418
|
throw new RangeError('RenderScene update identity must match its source snapshot');
|
|
374
419
|
}
|
|
375
|
-
|
|
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
|
+
});
|
|
376
436
|
this.deltaFrames += 1;
|
|
377
437
|
this.renderableScans = operations.length;
|
|
378
438
|
const pendingByWorld = new Map<number, Map<number, PendingIdentity>>();
|
|
@@ -414,7 +474,7 @@ export class RenderScene {
|
|
|
414
474
|
}
|
|
415
475
|
}
|
|
416
476
|
};
|
|
417
|
-
for (const operation of
|
|
477
|
+
for (const operation of preparedOperations) {
|
|
418
478
|
const pending = pendingFor(operation.worldId, operation.entityKey);
|
|
419
479
|
if (operation.kind === 'remove') {
|
|
420
480
|
pending.current = undefined;
|
|
@@ -423,7 +483,7 @@ export class RenderScene {
|
|
|
423
483
|
}
|
|
424
484
|
if (operation.snapshot !== undefined) {
|
|
425
485
|
const previousMaterials = pending.current?.materials;
|
|
426
|
-
const next =
|
|
486
|
+
const next = operation.snapshot;
|
|
427
487
|
pending.current =
|
|
428
488
|
previousMaterials !== undefined &&
|
|
429
489
|
previousMaterials.length === next.materials.length &&
|
|
@@ -439,10 +499,7 @@ export class RenderScene {
|
|
|
439
499
|
if (operation.instances !== undefined) {
|
|
440
500
|
pending.current = {
|
|
441
501
|
...pending.current,
|
|
442
|
-
instances:
|
|
443
|
-
...operation.instances,
|
|
444
|
-
transforms: new Float32Array(operation.instances.transforms),
|
|
445
|
-
},
|
|
502
|
+
instances: operation.instances,
|
|
446
503
|
};
|
|
447
504
|
pending.instanceChanged = true;
|
|
448
505
|
}
|
|
@@ -711,6 +768,11 @@ export class RenderScene {
|
|
|
711
768
|
return this.slotSnapshot;
|
|
712
769
|
}
|
|
713
770
|
|
|
771
|
+
/** Cheap owner revision for retained derived projections. */
|
|
772
|
+
revisionValue(): number {
|
|
773
|
+
return this.revision;
|
|
774
|
+
}
|
|
775
|
+
|
|
714
776
|
slot(worldId: number, entityKey: number): RenderSceneSlot | undefined {
|
|
715
777
|
return this.lookup(worldId, entityKey);
|
|
716
778
|
}
|
|
@@ -922,16 +984,36 @@ export class RenderScene {
|
|
|
922
984
|
reasons.includes('material-revision');
|
|
923
985
|
const previous = seedCurrent || submitted === undefined ? slot.snapshot : submitted.snapshot;
|
|
924
986
|
const previousWorld = this.previousWorldBySlot[slot.slot];
|
|
987
|
+
const currentInstances = slot.snapshot.instances;
|
|
988
|
+
const submittedInstances = submitted?.snapshot.instances;
|
|
989
|
+
const instancesCompatible =
|
|
990
|
+
currentInstances === undefined && submittedInstances === undefined
|
|
991
|
+
? true
|
|
992
|
+
: currentInstances !== undefined &&
|
|
993
|
+
submittedInstances !== undefined &&
|
|
994
|
+
(currentInstances.collectionId === undefined ||
|
|
995
|
+
submittedInstances.collectionId === undefined ||
|
|
996
|
+
currentInstances.collectionId === submittedInstances.collectionId) &&
|
|
997
|
+
currentInstances.transforms.length >= currentInstances.instanceCount * 16 &&
|
|
998
|
+
submittedInstances.transforms.length >= submittedInstances.instanceCount * 16 &&
|
|
999
|
+
sameInstanceIdentitySet(currentInstances.generations, submittedInstances.generations);
|
|
1000
|
+
const motionValid = !seedCurrent && previousWorld !== undefined && instancesCompatible;
|
|
925
1001
|
return {
|
|
926
1002
|
previousEpoch: seedCurrent ? undefined : this.submittedEpoch,
|
|
927
1003
|
previousSource: seedCurrent ? 'current-seed' : 'last-submitted',
|
|
1004
|
+
motionValid,
|
|
928
1005
|
reactive: reasons.length > 0,
|
|
929
1006
|
reactiveReasons: reasons,
|
|
930
1007
|
previousTransform:
|
|
931
1008
|
seedCurrent || previousWorld === undefined
|
|
932
1009
|
? previous.transform
|
|
933
1010
|
: { ...previous.transform, world: previousWorld },
|
|
934
|
-
|
|
1011
|
+
// A collection identity/count break is a temporal cut for that
|
|
1012
|
+
// renderable. The record stage receives the current snapshot as its
|
|
1013
|
+
// baseline, while stable collections retain the submitted column and
|
|
1014
|
+
// use identity generations to map reordered entries and seed replaced
|
|
1015
|
+
// entries.
|
|
1016
|
+
previousInstances: seedCurrent ? slot.snapshot.instances : previous.instances,
|
|
935
1017
|
previousSkin: previous.skin,
|
|
936
1018
|
previousMorphWeights: previous.morph?.weights,
|
|
937
1019
|
};
|
|
@@ -985,10 +1067,10 @@ export class RenderScene {
|
|
|
985
1067
|
export interface PersistentRenderSceneOptions {
|
|
986
1068
|
readonly getDevice?: (() => RhiDevice) | undefined;
|
|
987
1069
|
readonly onGpuError?: ((error: RhiError) => void) | undefined;
|
|
988
|
-
readonly
|
|
1070
|
+
readonly onRuntimeAssetChange?: ((worldId: number, handle: number) => void) | undefined;
|
|
989
1071
|
readonly configuredQueryBudget?: number | undefined;
|
|
990
|
-
/**
|
|
991
|
-
readonly instanceCollections?:
|
|
1072
|
+
/** Instance projection accepted by the same World source update flow. */
|
|
1073
|
+
readonly instanceCollections?: InstanceProjectionStore | undefined;
|
|
992
1074
|
}
|
|
993
1075
|
|
|
994
1076
|
export interface PersistentGpuDrivenState {
|
|
@@ -997,7 +1079,11 @@ export interface PersistentGpuDrivenState {
|
|
|
997
1079
|
readonly slots: readonly RenderSceneSlot[];
|
|
998
1080
|
/** Stable renderer-local World keys aligned with RenderSceneSlot.worldId. */
|
|
999
1081
|
readonly worldKeys?: readonly number[];
|
|
1082
|
+
/** Public World identities aligned with RenderSceneSlot.worldId. */
|
|
1083
|
+
readonly worldIdentities?: readonly string[];
|
|
1000
1084
|
readonly structureMetrics?: GpuDrivenStructureMetrics;
|
|
1085
|
+
/** Stable retained ProbeBlend upload projection from the Scene owner. */
|
|
1086
|
+
readonly probeBlend?: ProbeBlendBufferProjection;
|
|
1001
1087
|
}
|
|
1002
1088
|
|
|
1003
1089
|
export interface CpuDirectViewInput {
|
|
@@ -1075,7 +1161,11 @@ interface PersistentCompositionEntry {
|
|
|
1075
1161
|
readonly readVersions: RenderReadVersion[];
|
|
1076
1162
|
readonly leaseIdentities: readonly string[];
|
|
1077
1163
|
readonly transformQueries: readonly GlobalTransformChangeQuery[];
|
|
1078
|
-
readonly
|
|
1164
|
+
readonly sourceStates: readonly {
|
|
1165
|
+
projection: StateProjection;
|
|
1166
|
+
entities: Map<number, EntityHandle>;
|
|
1167
|
+
contentHandles: Map<number, readonly number[]>;
|
|
1168
|
+
}[];
|
|
1079
1169
|
readonly dispatchBySlot: Map<number, readonly DispatchEntry[]>;
|
|
1080
1170
|
dispatchRevision: number;
|
|
1081
1171
|
dispatchCache: { readonly revision: number; readonly value: DispatchEntry[] } | undefined;
|
|
@@ -1085,8 +1175,14 @@ interface PersistentCompositionEntry {
|
|
|
1085
1175
|
/** Slots retained for recovery but excluded from direct and indirect submission. */
|
|
1086
1176
|
readonly unavailableSlots: Set<number>;
|
|
1087
1177
|
catalogEpoch: number;
|
|
1088
|
-
instanceEpoch: number;
|
|
1089
1178
|
readonly probeProjection: ProbeBlendSceneProjection;
|
|
1179
|
+
probeObjects:
|
|
1180
|
+
| {
|
|
1181
|
+
readonly revision: number;
|
|
1182
|
+
readonly value: readonly ProbeSceneObjectInput[];
|
|
1183
|
+
readonly surfaceValue: readonly ProbeSceneObjectInput[];
|
|
1184
|
+
}
|
|
1185
|
+
| undefined;
|
|
1090
1186
|
temporalDemanded: boolean;
|
|
1091
1187
|
gpuDrivenSceneRequired: boolean;
|
|
1092
1188
|
}
|
|
@@ -1095,7 +1191,6 @@ interface PersistentCompositionEntry {
|
|
|
1095
1191
|
// environment facts are freshly extracted by deriveFramePlan on every draw;
|
|
1096
1192
|
// their edits must not recreate unrelated geometry or its submission history.
|
|
1097
1193
|
const RENDERABLE_SOURCE_COMPONENTS = [
|
|
1098
|
-
GlobalTransform,
|
|
1099
1194
|
ChildOf,
|
|
1100
1195
|
MeshFilter,
|
|
1101
1196
|
MeshRenderer,
|
|
@@ -1110,21 +1205,6 @@ const RENDERABLE_SOURCE_COMPONENTS = [
|
|
|
1110
1205
|
Lines,
|
|
1111
1206
|
SortKey,
|
|
1112
1207
|
] as const;
|
|
1113
|
-
const RENDERABLE_SOURCE_COMPONENT_IDS = new Set(
|
|
1114
|
-
RENDERABLE_SOURCE_COMPONENTS.map((component) => componentId(component)),
|
|
1115
|
-
);
|
|
1116
|
-
const VISIBILITY_DEPENDENCY_COMPONENT_IDS = new Set([
|
|
1117
|
-
componentId(ChildOf),
|
|
1118
|
-
componentId(Visibility),
|
|
1119
|
-
]);
|
|
1120
|
-
const STRUCTURAL_MEMBERSHIP_SCAN_COMPONENT_IDS = new Set([
|
|
1121
|
-
componentId(ChildOf),
|
|
1122
|
-
componentId(Layer),
|
|
1123
|
-
componentId(Visibility),
|
|
1124
|
-
componentId(SpriteRegionOverride),
|
|
1125
|
-
componentId(SortKey),
|
|
1126
|
-
]);
|
|
1127
|
-
|
|
1128
1208
|
function createGlobalTransformChangeQuery(world: World): GlobalTransformChangeQuery {
|
|
1129
1209
|
const result = world.query({ read: [GlobalTransform], changed: [GlobalTransform] });
|
|
1130
1210
|
if (!result.ok) throw result.error;
|
|
@@ -1135,29 +1215,43 @@ function createGlobalTransformChangeQuery(world: World): GlobalTransformChangeQu
|
|
|
1135
1215
|
return query;
|
|
1136
1216
|
}
|
|
1137
1217
|
|
|
1138
|
-
function
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
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 };
|
|
1154
1247
|
}
|
|
1155
1248
|
|
|
1156
|
-
function
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
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
|
+
);
|
|
1161
1255
|
}
|
|
1162
1256
|
|
|
1163
1257
|
function sourceMembershipChanged(world: World, slot: RenderSceneSlot): boolean {
|
|
@@ -1273,7 +1367,17 @@ function topologyDeltaForAvailable(
|
|
|
1273
1367
|
|
|
1274
1368
|
function frameDemandsTemporal(frame: ExtractedFrame): boolean {
|
|
1275
1369
|
const camera = frame.cameras[0];
|
|
1276
|
-
|
|
1370
|
+
const motionBlur = camera?.motionBlur;
|
|
1371
|
+
return (
|
|
1372
|
+
camera?.antialias === 'taa' ||
|
|
1373
|
+
(motionBlur !== undefined &&
|
|
1374
|
+
motionBlurTemporalDemand({
|
|
1375
|
+
shutterAngle: motionBlur.shutterAngle,
|
|
1376
|
+
maxRadiusPixels: motionBlur.maxRadiusPixels,
|
|
1377
|
+
sampleCount: motionBlur.sampleCount,
|
|
1378
|
+
targetFps: motionBlur.targetFps ?? 60,
|
|
1379
|
+
}))
|
|
1380
|
+
);
|
|
1277
1381
|
}
|
|
1278
1382
|
|
|
1279
1383
|
function cameraFrusta(cameras: readonly CameraSnapshot[]): readonly Float32Array[] {
|
|
@@ -1827,7 +1931,6 @@ export class PersistentRenderScene {
|
|
|
1827
1931
|
preserveVisibilityOnReorder,
|
|
1828
1932
|
);
|
|
1829
1933
|
}
|
|
1830
|
-
let requiresSourceRefresh = false;
|
|
1831
1934
|
const changedEntitiesByWorld = worlds.map(
|
|
1832
1935
|
(_, worldId) => new Set(entry.pendingRenderableEntitiesByWorld[worldId] ?? []),
|
|
1833
1936
|
);
|
|
@@ -1840,171 +1943,144 @@ export class PersistentRenderScene {
|
|
|
1840
1943
|
contentChangedByWorld[slot.worldId]?.add(slot.entityKey);
|
|
1841
1944
|
}
|
|
1842
1945
|
}
|
|
1843
|
-
const instanceEpoch = this.options.instanceCollections?.epoch ?? 0;
|
|
1844
|
-
if (entry.instanceEpoch !== instanceEpoch) {
|
|
1845
|
-
for (const slot of entry.projection.slotsSnapshot()) {
|
|
1846
|
-
const id = slot.snapshot.instances?.collectionId;
|
|
1847
|
-
if (id === undefined) continue;
|
|
1848
|
-
const current = this.options.instanceCollections?.inspect(id);
|
|
1849
|
-
if (!current?.ok || current.value.revision !== slot.snapshot.instances?.revision) {
|
|
1850
|
-
changedEntitiesByWorld[slot.worldId]?.add(slot.entityKey);
|
|
1851
|
-
}
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
1946
|
const nextReadVersions = entry.readVersions.slice();
|
|
1855
|
-
const
|
|
1856
|
-
const structuralComponentIdsByWorld = worlds.map(() => new Set<number>());
|
|
1857
|
-
let currentRenderableEntitiesByWorld: readonly (ReadonlySet<number> | undefined)[] | undefined;
|
|
1947
|
+
const sourceBatches: StateProjectionBatch[] = [];
|
|
1858
1948
|
const removedSlots: RenderSceneSlot[] = [];
|
|
1859
|
-
|
|
1949
|
+
const transformSpans: WorldTransformSpan[] = [];
|
|
1950
|
+
for (let worldId = 0; worldId < worlds.length; worldId++) {
|
|
1860
1951
|
const world = worlds[worldId];
|
|
1861
|
-
|
|
1862
|
-
const lease = leases
|
|
1863
|
-
if (lease === undefined || entry.leaseIdentities[worldId] !== lease.worldIdentity) {
|
|
1864
|
-
requiresSourceRefresh = true;
|
|
1865
|
-
break;
|
|
1866
|
-
}
|
|
1952
|
+
const source = entry.sourceStates[worldId];
|
|
1953
|
+
const lease = leases[worldId];
|
|
1867
1954
|
const version = entry.readVersions[worldId];
|
|
1868
|
-
if (
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
if (
|
|
1880
|
-
|
|
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();
|
|
1881
1970
|
}
|
|
1882
|
-
const
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
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));
|
|
1892
2003
|
}
|
|
2004
|
+
for (const handle of runtimeHandles) runtimeAssets.add(handle);
|
|
1893
2005
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
const query = entry.renderChangeQueries[worldId]?.get(changedComponentId);
|
|
1904
|
-
if (query !== undefined) {
|
|
1905
|
-
for (const row of query) {
|
|
1906
|
-
const entity = row.entity as number;
|
|
1907
|
-
if (VISIBILITY_DEPENDENCY_COMPONENT_IDS.has(changedComponentId)) {
|
|
1908
|
-
const affected = collectSubtree(world, row.entity);
|
|
1909
|
-
for (const dependent of affected) {
|
|
1910
|
-
if (
|
|
1911
|
-
!entry.projection.has(worldId, dependent) &&
|
|
1912
|
-
!world.hasComponent(dependent as EntityHandle, MeshRenderer)
|
|
1913
|
-
)
|
|
1914
|
-
continue;
|
|
1915
|
-
changed.add(dependent);
|
|
1916
|
-
otherChanged?.add(dependent);
|
|
1917
|
-
}
|
|
1918
|
-
} else {
|
|
1919
|
-
changed.add(entity);
|
|
1920
|
-
if (changedComponentId !== componentId(Instances)) otherChanged?.add(entity);
|
|
1921
|
-
}
|
|
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);
|
|
1922
2015
|
}
|
|
1923
|
-
|
|
1924
|
-
}
|
|
1925
|
-
if (requiresSourceRefresh) break;
|
|
1926
|
-
nextReadVersions[worldId] = read.version;
|
|
1927
|
-
}
|
|
1928
|
-
if (requiresSourceRefresh) {
|
|
1929
|
-
return this.reconcileComposition(worlds, owner, catalogEpoch, buildCandidateFrame, leases);
|
|
1930
|
-
}
|
|
1931
|
-
|
|
1932
|
-
const transformSpans: WorldTransformSpan[] = [];
|
|
1933
|
-
for (let worldId = 0; worldId < entry.transformQueries.length; worldId += 1) {
|
|
1934
|
-
const query = entry.transformQueries[worldId];
|
|
1935
|
-
if (query === undefined) continue;
|
|
1936
|
-
for (const span of query.spans().unwrap()) {
|
|
1937
|
-
const changedWorlds = span.get(GlobalTransform).world;
|
|
1938
|
-
if (!(changedWorlds instanceof Float32Array)) {
|
|
1939
|
-
requiresSourceRefresh = true;
|
|
1940
|
-
break;
|
|
1941
|
-
}
|
|
1942
|
-
transformSpans.push({ worldId, entities: span.entities, worlds: changedWorlds });
|
|
1943
|
-
for (const entity of span.entities) {
|
|
1944
|
-
for (const consumer of entry.skinConsumersByJoint.get(skinJointKey(worldId, entity)) ??
|
|
2016
|
+
for (const consumer of entry.skinConsumersByJoint.get(skinJointKey(worldId, previous)) ??
|
|
1945
2017
|
[]) {
|
|
1946
|
-
|
|
1947
|
-
|
|
2018
|
+
changed.add(consumer);
|
|
2019
|
+
content.add(consumer);
|
|
1948
2020
|
}
|
|
1949
2021
|
}
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
if (
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
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);
|
|
1982
2057
|
}
|
|
1983
2058
|
}
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
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
|
+
}
|
|
1999
2081
|
}
|
|
2000
2082
|
}
|
|
2001
2083
|
}
|
|
2002
|
-
for (const slot of entry.projection.slotsSnapshot()) {
|
|
2003
|
-
if (slot.worldId !== worldId || current.has(slot.entityKey)) continue;
|
|
2004
|
-
removedSlots.push(slot);
|
|
2005
|
-
changedEntitiesByWorld[worldId]?.add(slot.entityKey);
|
|
2006
|
-
}
|
|
2007
|
-
this.worldEntitiesScanned += current.size;
|
|
2008
2084
|
}
|
|
2009
2085
|
}
|
|
2010
2086
|
|
|
@@ -2017,6 +2093,8 @@ export class PersistentRenderScene {
|
|
|
2017
2093
|
for (const entityKey of changedEntitiesByWorld[worldId] ?? []) pending.add(entityKey);
|
|
2018
2094
|
}
|
|
2019
2095
|
|
|
2096
|
+
const resourceFrame = buildCandidateFrame('none');
|
|
2097
|
+
for (const batch of sourceBatches) batch.validate();
|
|
2020
2098
|
let changedDelta: RenderSceneApplyResult | undefined;
|
|
2021
2099
|
const hasChangedEntities = changedEntitiesByWorld.some((entities) => entities.size > 0);
|
|
2022
2100
|
if (hasChangedEntities || removedSlots.length > 0 || transformSpans.length > 0) {
|
|
@@ -2031,9 +2109,6 @@ export class PersistentRenderScene {
|
|
|
2031
2109
|
}
|
|
2032
2110
|
for (const slot of removedSlots) {
|
|
2033
2111
|
operations.push({ kind: 'remove', worldId: slot.worldId, entityKey: slot.entityKey });
|
|
2034
|
-
if (slot.snapshot.skinJointEntities !== undefined) {
|
|
2035
|
-
removeSkinConsumer(entry.skinConsumersByJoint, slot.snapshot);
|
|
2036
|
-
}
|
|
2037
2112
|
for (
|
|
2038
2113
|
let materialIndex = 0;
|
|
2039
2114
|
materialIndex < slot.snapshot.materials.length;
|
|
@@ -2090,7 +2165,23 @@ export class PersistentRenderScene {
|
|
|
2090
2165
|
});
|
|
2091
2166
|
publishedEntitiesByWorld[snapshot.worldId]?.add(snapshot.entityKey);
|
|
2092
2167
|
}
|
|
2168
|
+
for (const batch of sourceBatches) batch.validate();
|
|
2093
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);
|
|
2094
2185
|
const publishedSkinKeys = new Set<string>();
|
|
2095
2186
|
for (const snapshot of partial?.renderables ?? []) {
|
|
2096
2187
|
publishedSkinKeys.add(`${snapshot.worldId}:${snapshot.entityKey}`);
|
|
@@ -2126,7 +2217,7 @@ export class PersistentRenderScene {
|
|
|
2126
2217
|
return (
|
|
2127
2218
|
worldId !== undefined &&
|
|
2128
2219
|
!changedEntitiesByWorld[worldId]?.has(report.entity) &&
|
|
2129
|
-
|
|
2220
|
+
isRenderableMember(report.world, report.entity)
|
|
2130
2221
|
);
|
|
2131
2222
|
}),
|
|
2132
2223
|
...(partial?.hiddenEntityReports ?? []),
|
|
@@ -2155,8 +2246,9 @@ export class PersistentRenderScene {
|
|
|
2155
2246
|
continue;
|
|
2156
2247
|
}
|
|
2157
2248
|
if (slot === undefined) {
|
|
2158
|
-
const
|
|
2159
|
-
if (
|
|
2249
|
+
const world = worlds[worldId];
|
|
2250
|
+
if (world !== undefined && !isRenderableMember(world, entityKey))
|
|
2251
|
+
pending?.delete(entityKey);
|
|
2160
2252
|
continue;
|
|
2161
2253
|
}
|
|
2162
2254
|
// The producer did not publish this requested identity. Keep the
|
|
@@ -2207,9 +2299,43 @@ export class PersistentRenderScene {
|
|
|
2207
2299
|
this.noChangeFrames += 1;
|
|
2208
2300
|
this.syncGpuOwner(entry.token, entry.projection);
|
|
2209
2301
|
}
|
|
2210
|
-
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
|
+
}
|
|
2211
2338
|
entry.catalogEpoch = catalogEpoch;
|
|
2212
|
-
entry.instanceEpoch = instanceEpoch;
|
|
2213
2339
|
for (let worldId = 0; worldId < nextReadVersions.length; worldId += 1) {
|
|
2214
2340
|
const version = nextReadVersions[worldId];
|
|
2215
2341
|
if (version !== undefined) entry.readVersions[worldId] = version;
|
|
@@ -2256,11 +2382,13 @@ export class PersistentRenderScene {
|
|
|
2256
2382
|
this.stableSlotByEntity.clear();
|
|
2257
2383
|
}
|
|
2258
2384
|
if (this.gpuOwner !== world && this.gpuOwner !== detachedComposition?.token) return;
|
|
2259
|
-
|
|
2260
|
-
|
|
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.
|
|
2261
2390
|
this.gpuOwner = undefined;
|
|
2262
|
-
this.
|
|
2263
|
-
this.gpuStatus = 'inactive';
|
|
2391
|
+
this.gpuStatus = this.gpuScene === undefined ? 'inactive' : 'resident';
|
|
2264
2392
|
}
|
|
2265
2393
|
|
|
2266
2394
|
/** Drop only device-owned tables; the CPU projection remains the recovery authority. */
|
|
@@ -2326,6 +2454,9 @@ export class PersistentRenderScene {
|
|
|
2326
2454
|
scene,
|
|
2327
2455
|
plan: composition.topology.plan(),
|
|
2328
2456
|
slots,
|
|
2457
|
+
worldKeys: composition.worldKeys,
|
|
2458
|
+
worldIdentities: composition.worlds.map((world) => world.identity),
|
|
2459
|
+
probeBlend: composition.probeProjection.recordBufferProjection(),
|
|
2329
2460
|
});
|
|
2330
2461
|
let published = false;
|
|
2331
2462
|
let released = false;
|
|
@@ -2497,11 +2628,13 @@ export class PersistentRenderScene {
|
|
|
2497
2628
|
plan: entry.topology.plan(),
|
|
2498
2629
|
slots: entry.projection.slotsSnapshot(),
|
|
2499
2630
|
worldKeys: entry.worldKeys,
|
|
2631
|
+
worldIdentities: entry.worlds.map((world) => world.identity),
|
|
2500
2632
|
structureMetrics: {
|
|
2501
2633
|
worldEntitiesScanned: this.worldEntitiesScanned,
|
|
2502
2634
|
sceneTableUploadBytes: this.sceneTableUploadBytes,
|
|
2503
2635
|
paletteUploadBytes: 0,
|
|
2504
2636
|
},
|
|
2637
|
+
probeBlend: entry.probeProjection.recordBufferProjection(),
|
|
2505
2638
|
};
|
|
2506
2639
|
}
|
|
2507
2640
|
|
|
@@ -2510,13 +2643,17 @@ export class PersistentRenderScene {
|
|
|
2510
2643
|
// Previous transforms are consumed only by TAA and motion blur. Ordinary
|
|
2511
2644
|
// frames must not copy and upload the complete GPU transform table.
|
|
2512
2645
|
const gpuCommit = this.gpuScene?.commitTemporalFrame(this.temporalCapture !== undefined);
|
|
2513
|
-
if (gpuCommit !== undefined && !gpuCommit.ok)
|
|
2646
|
+
if (gpuCommit !== undefined && !gpuCommit.ok) {
|
|
2647
|
+
this.temporalCapture = undefined;
|
|
2648
|
+
return gpuCommit;
|
|
2649
|
+
}
|
|
2514
2650
|
const temporalCapture = this.temporalCapture;
|
|
2515
2651
|
if (temporalCapture !== undefined) {
|
|
2516
2652
|
try {
|
|
2517
2653
|
temporalCapture.projection.commitSubmission(temporalCapture.capture);
|
|
2518
2654
|
} catch (cause) {
|
|
2519
2655
|
void cause;
|
|
2656
|
+
this.temporalCapture = undefined;
|
|
2520
2657
|
return err(
|
|
2521
2658
|
new RhiError({
|
|
2522
2659
|
code: 'internal-error',
|
|
@@ -2530,6 +2667,11 @@ export class PersistentRenderScene {
|
|
|
2530
2667
|
return ok(undefined);
|
|
2531
2668
|
}
|
|
2532
2669
|
|
|
2670
|
+
/** Drop a staged temporal capture when the owning frame did not submit. */
|
|
2671
|
+
discardTemporalFrame(): void {
|
|
2672
|
+
this.temporalCapture = undefined;
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2533
2675
|
/** Capture current CPU scene facts; commitTemporalFrame publishes them only after submit. */
|
|
2534
2676
|
prepareTemporalFrame(
|
|
2535
2677
|
visible: readonly Pick<RenderableSnapshot, 'worldId' | 'entityKey'>[],
|
|
@@ -2566,7 +2708,12 @@ export class PersistentRenderScene {
|
|
|
2566
2708
|
preserveVisibilityOnReorder = false,
|
|
2567
2709
|
): ExtractedFrame {
|
|
2568
2710
|
const previousEntry = this.composition;
|
|
2569
|
-
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();
|
|
2570
2717
|
this.temporalCapture = undefined;
|
|
2571
2718
|
this.worldEntitiesScanned = candidateFrame.renderables.length;
|
|
2572
2719
|
const worldKeys = this.visibilityWorldKeysFor(worlds);
|
|
@@ -2594,38 +2741,14 @@ export class PersistentRenderScene {
|
|
|
2594
2741
|
this.invalidateActiveEntityRevision();
|
|
2595
2742
|
}
|
|
2596
2743
|
}
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
// primitive's slot/generation. Dispatch is remapped below to the sorted
|
|
2600
|
-
// renderable projection and remains frame-order independent.
|
|
2601
|
-
const sorted = candidateFrame.renderables
|
|
2602
|
-
.map((snapshot, sourceIndex) => ({ snapshot, sourceIndex }))
|
|
2603
|
-
.sort((left, right) => {
|
|
2604
|
-
const leftWorld = worldKeys[left.snapshot.worldId] ?? left.snapshot.worldId;
|
|
2605
|
-
const rightWorld = worldKeys[right.snapshot.worldId] ?? right.snapshot.worldId;
|
|
2606
|
-
return leftWorld - rightWorld || left.snapshot.entityKey - right.snapshot.entityKey;
|
|
2607
|
-
});
|
|
2608
|
-
const sortedRenderables = sorted.map(({ snapshot }) => snapshot);
|
|
2609
|
-
const renderableIndex = new Int32Array(candidateFrame.renderables.length);
|
|
2610
|
-
for (let index = 0; index < sorted.length; index += 1) {
|
|
2611
|
-
const sourceIndex = sorted[index]?.sourceIndex;
|
|
2612
|
-
if (sourceIndex !== undefined) renderableIndex[sourceIndex] = index;
|
|
2613
|
-
}
|
|
2614
|
-
const sortedDispatch = candidateFrame.dispatch.flatMap((entry) => {
|
|
2615
|
-
const index = renderableIndex[entry.renderableIndex];
|
|
2616
|
-
return index === undefined ? [] : [{ ...entry, renderableIndex: index }];
|
|
2617
|
-
});
|
|
2618
|
-
const stableCandidateFrame = {
|
|
2619
|
-
...candidateFrame,
|
|
2620
|
-
renderables: sortedRenderables,
|
|
2621
|
-
dispatch: sortedDispatch,
|
|
2622
|
-
};
|
|
2744
|
+
const stableCandidateFrame = candidateFrame;
|
|
2745
|
+
const renderables = candidateFrame.renderables;
|
|
2623
2746
|
const projection = previousEntry?.projection ?? new RenderScene();
|
|
2624
2747
|
if (previousEntry !== undefined) {
|
|
2625
2748
|
projection.remapWorlds(previousEntry.worlds.map((world) => worlds.indexOf(world)));
|
|
2626
2749
|
}
|
|
2627
2750
|
const desired = new Set(
|
|
2628
|
-
|
|
2751
|
+
renderables.map((snapshot) => identityKey(snapshot.worldId, snapshot.entityKey)),
|
|
2629
2752
|
);
|
|
2630
2753
|
const operations: RenderSceneOperation[] = [];
|
|
2631
2754
|
for (const slot of projection.slotsSnapshot()) {
|
|
@@ -2633,7 +2756,7 @@ export class PersistentRenderScene {
|
|
|
2633
2756
|
operations.push({ kind: 'remove', worldId: slot.worldId, entityKey: slot.entityKey });
|
|
2634
2757
|
}
|
|
2635
2758
|
}
|
|
2636
|
-
for (const snapshot of
|
|
2759
|
+
for (const snapshot of renderables) {
|
|
2637
2760
|
operations.push({
|
|
2638
2761
|
kind: 'update',
|
|
2639
2762
|
worldId: snapshot.worldId,
|
|
@@ -2642,6 +2765,22 @@ export class PersistentRenderScene {
|
|
|
2642
2765
|
});
|
|
2643
2766
|
}
|
|
2644
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
|
+
);
|
|
2645
2784
|
this.stableSlotByEntity.clear();
|
|
2646
2785
|
for (const slot of projection.slotsSnapshot()) {
|
|
2647
2786
|
const stableWorld = worldKeys[slot.worldId] ?? slot.worldId;
|
|
@@ -2676,10 +2815,7 @@ export class PersistentRenderScene {
|
|
|
2676
2815
|
leases === undefined || leases.length !== worlds.length
|
|
2677
2816
|
? []
|
|
2678
2817
|
: worlds.map(createGlobalTransformChangeQuery),
|
|
2679
|
-
|
|
2680
|
-
leases === undefined || leases.length !== worlds.length
|
|
2681
|
-
? []
|
|
2682
|
-
: worlds.map(createRenderChangeQueries),
|
|
2818
|
+
sourceStates,
|
|
2683
2819
|
dispatchBySlot: dispatchEntriesBySlot(stableCandidateFrame, projection),
|
|
2684
2820
|
dispatchRevision: 0,
|
|
2685
2821
|
dispatchCache: undefined,
|
|
@@ -2687,8 +2823,8 @@ export class PersistentRenderScene {
|
|
|
2687
2823
|
pendingRenderableEntitiesByWorld: worlds.map(() => new Set<number>()),
|
|
2688
2824
|
unavailableSlots: new Set<number>(),
|
|
2689
2825
|
catalogEpoch,
|
|
2690
|
-
instanceEpoch: this.options.instanceCollections?.epoch ?? 0,
|
|
2691
2826
|
probeProjection: new ProbeBlendSceneProjection(),
|
|
2827
|
+
probeObjects: undefined,
|
|
2692
2828
|
temporalDemanded: frameDemandsTemporal(candidateFrame),
|
|
2693
2829
|
gpuDrivenSceneRequired: true,
|
|
2694
2830
|
};
|
|
@@ -2723,6 +2859,7 @@ export class PersistentRenderScene {
|
|
|
2723
2859
|
? projection.cullingWorldBounds(snapshot)
|
|
2724
2860
|
: projection.cullingWorldBoundsAt(slot);
|
|
2725
2861
|
});
|
|
2862
|
+
for (const source of sourceStates) source.batch.accept();
|
|
2726
2863
|
this.frameEpoch += 1;
|
|
2727
2864
|
this.visibilityFacetFrame = undefined;
|
|
2728
2865
|
this.visibilityProjectionCache = undefined;
|
|
@@ -2745,9 +2882,8 @@ export class PersistentRenderScene {
|
|
|
2745
2882
|
*/
|
|
2746
2883
|
private deriveFramePlan(
|
|
2747
2884
|
entry: PersistentCompositionEntry,
|
|
2748
|
-
|
|
2885
|
+
resourceFrame: ExtractedFrame,
|
|
2749
2886
|
): ExtractedFrame {
|
|
2750
|
-
const resourceFrame = buildCandidateFrame('none');
|
|
2751
2887
|
const cachedDispatch = entry.dispatchCache;
|
|
2752
2888
|
const dispatch =
|
|
2753
2889
|
cachedDispatch?.revision === entry.dispatchRevision
|
|
@@ -2857,27 +2993,41 @@ export class PersistentRenderScene {
|
|
|
2857
2993
|
] as [number, number, number],
|
|
2858
2994
|
};
|
|
2859
2995
|
const probes = frame.lightProbes ?? [];
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
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
|
+
};
|
|
2867
3023
|
}
|
|
2868
|
-
const
|
|
2869
|
-
objectKey: slot.slot,
|
|
2870
|
-
generation: slot.generation,
|
|
2871
|
-
position: [
|
|
2872
|
-
slot.snapshot.transform.world[12] ?? 0,
|
|
2873
|
-
slot.snapshot.transform.world[13] ?? 0,
|
|
2874
|
-
slot.snapshot.transform.world[14] ?? 0,
|
|
2875
|
-
],
|
|
2876
|
-
}));
|
|
3024
|
+
const surfaceOnly = probes.length === 0;
|
|
2877
3025
|
entry.probeProjection.apply({
|
|
2878
|
-
objects,
|
|
3026
|
+
objects: surfaceOnly ? entry.probeObjects.surfaceValue : entry.probeObjects.value,
|
|
2879
3027
|
probes,
|
|
2880
3028
|
sky,
|
|
3029
|
+
worldRevision: revision,
|
|
3030
|
+
...(surfaceOnly ? { retainSkyResidualRecords: true } : {}),
|
|
2881
3031
|
});
|
|
2882
3032
|
}
|
|
2883
3033
|
|
|
@@ -2912,7 +3062,7 @@ export class PersistentRenderScene {
|
|
|
2912
3062
|
recreatedSlots: [],
|
|
2913
3063
|
resynced: 0,
|
|
2914
3064
|
})
|
|
2915
|
-
: acquired.scene.sync(delta);
|
|
3065
|
+
: acquired.scene.sync(delta, (slot) => projection.temporalSnapshotBySlot(slot.slot));
|
|
2916
3066
|
if (!result.ok) {
|
|
2917
3067
|
this.sceneTableUploadBytes = 0;
|
|
2918
3068
|
this.failGpu(result.error);
|