@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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Buffer, MappedBuffer, RhiDevice, Texture } from '@forgeax/engine-rhi';
|
|
2
|
+
import { ok } from '@forgeax/engine-types';
|
|
3
|
+
import { expect, it, vi } from 'vitest';
|
|
4
|
+
import { createRendererObservationCaptureOwner } from '../assembly/webgpu-renderer-observation-owner';
|
|
5
|
+
|
|
6
|
+
function deferred<T>(): { readonly promise: Promise<T>; readonly resolve: (value: T) => void } {
|
|
7
|
+
let resolve!: (value: T) => void;
|
|
8
|
+
const promise = new Promise<T>((next) => {
|
|
9
|
+
resolve = next;
|
|
10
|
+
});
|
|
11
|
+
return { promise, resolve };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
it('retires a receipt observation readback only after its pending map completes', async () => {
|
|
15
|
+
const mapStarted = deferred<void>();
|
|
16
|
+
const mapCompleted = deferred<ReturnType<typeof ok<MappedBuffer>>>();
|
|
17
|
+
const mappedBytes = new ArrayBuffer(256);
|
|
18
|
+
const unmap = vi.fn();
|
|
19
|
+
const buffer = {
|
|
20
|
+
mapAsync: async () => {
|
|
21
|
+
mapStarted.resolve();
|
|
22
|
+
return mapCompleted.promise;
|
|
23
|
+
},
|
|
24
|
+
} as unknown as Buffer;
|
|
25
|
+
const texture = {} as Texture;
|
|
26
|
+
const destroyBuffer = vi.fn(() => ok(undefined));
|
|
27
|
+
const device = { destroyBuffer } as unknown as RhiDevice;
|
|
28
|
+
const errors: unknown[] = [];
|
|
29
|
+
const owner = createRendererObservationCaptureOwner((error) => errors.push(error));
|
|
30
|
+
const capture = {
|
|
31
|
+
domain: 'linear-hdr' as const,
|
|
32
|
+
format: 'rgba8unorm' as const,
|
|
33
|
+
device,
|
|
34
|
+
texture,
|
|
35
|
+
buffer,
|
|
36
|
+
frameNumber: 17,
|
|
37
|
+
deviceGeneration: 3,
|
|
38
|
+
graphGeneration: 9,
|
|
39
|
+
backendId: 'null' as const,
|
|
40
|
+
width: 1,
|
|
41
|
+
height: 1,
|
|
42
|
+
bytesPerRow: 256,
|
|
43
|
+
};
|
|
44
|
+
owner.observationCaptureOwner.register(capture);
|
|
45
|
+
expect(owner.observationCaptureOwner.consume(17)).toEqual([capture]);
|
|
46
|
+
|
|
47
|
+
const pending = owner.readObservationCapture(capture);
|
|
48
|
+
await mapStarted.promise;
|
|
49
|
+
expect(destroyBuffer).not.toHaveBeenCalled();
|
|
50
|
+
expect(owner.stats).toMatchObject({ liveCount: 1, mapCount: 1, readbackCount: 0 });
|
|
51
|
+
|
|
52
|
+
mapCompleted.resolve(
|
|
53
|
+
ok({
|
|
54
|
+
getMappedRange: () => ok(mappedBytes),
|
|
55
|
+
unmap,
|
|
56
|
+
} as unknown as MappedBuffer),
|
|
57
|
+
);
|
|
58
|
+
await expect(pending).resolves.toMatchObject({ ok: true, value: new Uint8Array(256) });
|
|
59
|
+
expect(unmap).toHaveBeenCalledTimes(1);
|
|
60
|
+
expect(destroyBuffer).toHaveBeenCalledTimes(1);
|
|
61
|
+
expect(owner.stats).toMatchObject({ liveCount: 0, mapCount: 1, readbackCount: 1 });
|
|
62
|
+
expect(errors).toEqual([]);
|
|
63
|
+
expect(owner.disposeReceiptObservationCaptures()).toBeUndefined();
|
|
64
|
+
expect(destroyBuffer).toHaveBeenCalledTimes(1);
|
|
65
|
+
});
|
|
@@ -22,6 +22,10 @@ const rendererRecoverySource = readFileSync(
|
|
|
22
22
|
resolve(import.meta.dirname, '../assembly/recovery/renderer-recover.ts'),
|
|
23
23
|
'utf8',
|
|
24
24
|
);
|
|
25
|
+
const recoveryPipelineSource = readFileSync(
|
|
26
|
+
resolve(import.meta.dirname, '../record/recovery-pipeline.ts'),
|
|
27
|
+
'utf8',
|
|
28
|
+
);
|
|
25
29
|
|
|
26
30
|
describe('recovery candidate preparation contract', () => {
|
|
27
31
|
it('does not restore the lost device SSR history when publishing a detached candidate', () => {
|
|
@@ -145,6 +149,31 @@ describe('recovery candidate preparation contract', () => {
|
|
|
145
149
|
expect(resolver).not.toContain('internals.device.limits');
|
|
146
150
|
});
|
|
147
151
|
|
|
152
|
+
it('rehydrates capability variants before copying late-installed material declarations', () => {
|
|
153
|
+
const preparation = rendererRecoverySource.indexOf('await prepareMaterialShaders(');
|
|
154
|
+
const copy = rendererRecoverySource.indexOf(
|
|
155
|
+
'const activeShaderCatalog = getActiveShaderState().shaderInstance',
|
|
156
|
+
);
|
|
157
|
+
expect(preparation).toBeGreaterThanOrEqual(0);
|
|
158
|
+
expect(copy).toBeGreaterThan(preparation);
|
|
159
|
+
const copyBlock = rendererRecoverySource.slice(copy);
|
|
160
|
+
expect(copyBlock).toContain('candidateShaderCatalog.findMaterialArtifact(identifier).ok');
|
|
161
|
+
expect(copyBlock).toContain('candidateShaderCatalog.installMaterialArtifact(identifier');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('rehydrates Surface dynamic page bytes before candidate GPU preparation', () => {
|
|
165
|
+
const start = recoveryCandidateSource.indexOf('let recoverySurfaceDynamicInput =');
|
|
166
|
+
const end = recoveryCandidateSource.indexOf(
|
|
167
|
+
'if (candidateGpuDrivenScene.state !== undefined)',
|
|
168
|
+
start,
|
|
169
|
+
);
|
|
170
|
+
const surface = recoveryCandidateSource.slice(start, end);
|
|
171
|
+
expect(surface).toContain('candidateSurfacePage.bytes.set(source.page.bytes)');
|
|
172
|
+
expect(surface.indexOf('candidateSurfacePage.bytes.set(source.page.bytes)')).toBeLessThan(
|
|
173
|
+
surface.indexOf('recoverySurfaceDynamicInput = {'),
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
|
|
148
177
|
it('keeps render-system residency bindings live across publication', () => {
|
|
149
178
|
const start = rendererSource.indexOf('const renderSystem: RenderSystem = createRenderSystem({');
|
|
150
179
|
const end = rendererSource.indexOf('errorRegistry: internals.errorRegistry', start);
|
|
@@ -155,4 +184,44 @@ describe('recovery candidate preparation contract', () => {
|
|
|
155
184
|
expect(assembly).not.toMatch(/\n\s*gpuStore,\n/);
|
|
156
185
|
expect(assembly).not.toMatch(/\n\s*dynamicTextureStore,\n/);
|
|
157
186
|
});
|
|
187
|
+
|
|
188
|
+
it('rebuilds candidate shaders from accepted receipts with candidate-bound adapters', () => {
|
|
189
|
+
expect(rendererRecoverySource).toContain('entry.value.receipt === undefined');
|
|
190
|
+
expect(rendererRecoverySource).toContain('{ receipt: entry.value.receipt }');
|
|
191
|
+
expect(rendererRecoverySource).toContain(
|
|
192
|
+
'getShaderModuleAdapter().createShaderModule(descriptor)',
|
|
193
|
+
);
|
|
194
|
+
expect(rendererRecoverySource).toContain(
|
|
195
|
+
'getImmediateShaderModuleAdapter().createShaderModule(descriptor)',
|
|
196
|
+
);
|
|
197
|
+
expect(renderSystemSource).toContain('materialArtifacts: frameState.recoveryMaterialArtifacts');
|
|
198
|
+
expect(recoveryCandidateSource).toContain('materialArtifacts.size === 0');
|
|
199
|
+
expect(recoveryCandidateSource).toContain('{ materialArtifacts }');
|
|
200
|
+
expect(recoveryCandidateSource).toContain('domain: range.domain');
|
|
201
|
+
expect(recoveryCandidateSource).not.toContain('recovery-water-domain');
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('prepares the submitted forward specialization with the direct Surface ABI', () => {
|
|
205
|
+
expect(recoveryPipelineSource).toContain('readonly dispatch: readonly DispatchEntry[]');
|
|
206
|
+
expect(recoveryPipelineSource).toContain(
|
|
207
|
+
"candidate.tags.LightMode !== 'Forward' || candidate.materialShaderId === undefined",
|
|
208
|
+
);
|
|
209
|
+
expect(recoveryPipelineSource).toContain('forwardProgram?.materialShaderId');
|
|
210
|
+
expect(recoveryPipelineSource).toContain("'surface-direct-cluster-pbr' as const");
|
|
211
|
+
expect(recoveryPipelineSource).toContain("'surface-direct-pbr' as const");
|
|
212
|
+
expect(recoveryPipelineSource).toContain("'immediate',");
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('retires the candidate display view before publishing its prepared owners', () => {
|
|
216
|
+
const start = recoveryCandidateSource.indexOf('const publishRecoveryGraphCandidate');
|
|
217
|
+
const publish = recoveryCandidateSource.slice(start);
|
|
218
|
+
const retire = publish.indexOf('candidateDisplayGraph?.retire()');
|
|
219
|
+
const publication = publish.indexOf('Object.assign(frameState, candidate.frameState)');
|
|
220
|
+
|
|
221
|
+
expect(retire).toBeGreaterThanOrEqual(0);
|
|
222
|
+
expect(publication).toBeGreaterThan(retire);
|
|
223
|
+
expect(publish).toContain('candidate.frameState.compiledFrameGraph = null');
|
|
224
|
+
expect(publish).toContain('candidate.frameState.compiledFrameGraphTopologyKey = null');
|
|
225
|
+
expect(publish).toContain('candidate.frameState.perFrameGraph = null');
|
|
226
|
+
});
|
|
158
227
|
});
|
|
@@ -39,6 +39,9 @@ const expectedCodes = [
|
|
|
39
39
|
'dynamic-resolution-invalid-parameter',
|
|
40
40
|
'dynamic-resolution-requires-taa',
|
|
41
41
|
'dynamic-resolution-timing-unavailable',
|
|
42
|
+
'barrel-distortion-invalid-parameter',
|
|
43
|
+
'motion-blur-invalid-params',
|
|
44
|
+
|
|
42
45
|
'shadow-invalid-config',
|
|
43
46
|
'equirect-projection-failed',
|
|
44
47
|
'standard-light-budget-exceeded',
|
|
@@ -63,6 +66,7 @@ const expectedCodes = [
|
|
|
63
66
|
'render-feature-draw-recording-failed',
|
|
64
67
|
'environment-source-conflict',
|
|
65
68
|
'fog-cardinality',
|
|
69
|
+
'sun-cardinality',
|
|
66
70
|
'taa-caps-insufficient',
|
|
67
71
|
'environment-generation-failed',
|
|
68
72
|
'atmosphere-invalid-parameter',
|
|
@@ -85,6 +89,11 @@ const expectedCodes = [
|
|
|
85
89
|
'volume-invalid-bounds',
|
|
86
90
|
'volume-invalid-parameters',
|
|
87
91
|
'projector-binding-failed',
|
|
92
|
+
'cloud-layer-invalid-parameter',
|
|
93
|
+
'cloud-layer-owner-conflict',
|
|
94
|
+
'cloud-layer-cache-invalid',
|
|
95
|
+
'cloud-layer-capability-missing',
|
|
96
|
+
'cloud-layer-resource-failed',
|
|
88
97
|
] as const satisfies readonly RenderErrorCode[];
|
|
89
98
|
type ExpectedCodeUnion = (typeof expectedCodes)[number];
|
|
90
99
|
|
|
@@ -12,7 +12,17 @@ function gatedFeature(): RenderFeature<{ readonly frame: number }> {
|
|
|
12
12
|
identity: 'synthetic.gated',
|
|
13
13
|
requiredCapabilities: ['compute'],
|
|
14
14
|
extract: ({ frameNumber }) => ok({ frame: frameNumber }),
|
|
15
|
-
plan: () =>
|
|
15
|
+
plan: () =>
|
|
16
|
+
ok({
|
|
17
|
+
resources: [
|
|
18
|
+
{
|
|
19
|
+
kind: 'fullscreen-program' as const,
|
|
20
|
+
name: 'synthetic.gated.program',
|
|
21
|
+
source: 'synthetic',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
passes: [],
|
|
25
|
+
}),
|
|
16
26
|
};
|
|
17
27
|
}
|
|
18
28
|
|
|
@@ -82,7 +92,10 @@ describe('render feature diagnostics and capability gate', () => {
|
|
|
82
92
|
caps: caps(false),
|
|
83
93
|
});
|
|
84
94
|
|
|
85
|
-
expect(first.stageEvents).toEqual([
|
|
95
|
+
expect(first.stageEvents).toEqual([
|
|
96
|
+
{ featureIdentity: 'synthetic.gated', order: 0, stage: 'extract' },
|
|
97
|
+
{ featureIdentity: 'synthetic.gated', order: 0, stage: 'plan' },
|
|
98
|
+
]);
|
|
86
99
|
expect(first.errors).toHaveLength(1);
|
|
87
100
|
expect(first.errors[0]?.code).toBe('render-feature-capability-missing');
|
|
88
101
|
expect(host.diagnostics()[0]?.status).toBe('disabled');
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { type RenderError, RenderFeatureStageFailedError } from '../errors/render.js';
|
|
3
|
+
import {
|
|
4
|
+
PENDING_RENDER_FEATURE_ERROR_REPORT_INTERVAL_FRAMES,
|
|
5
|
+
type PendingRenderFeatureErrorReport,
|
|
6
|
+
reportPendingRenderFeatureErrors,
|
|
7
|
+
shouldReportPendingRenderFeatureError,
|
|
8
|
+
} from '../features/error-reporting.js';
|
|
9
|
+
|
|
10
|
+
describe('pending render-feature error reporting', () => {
|
|
11
|
+
it('reports the first failure, suppresses the hot-loop, and reopens the cooldown', () => {
|
|
12
|
+
const lastReportedFrame = new Map<string, PendingRenderFeatureErrorReport>();
|
|
13
|
+
expect(shouldReportPendingRenderFeatureError(lastReportedFrame, 'feature\0plan', 10)).toBe(
|
|
14
|
+
true,
|
|
15
|
+
);
|
|
16
|
+
expect(shouldReportPendingRenderFeatureError(lastReportedFrame, 'feature\0plan', 11)).toBe(
|
|
17
|
+
false,
|
|
18
|
+
);
|
|
19
|
+
expect(
|
|
20
|
+
shouldReportPendingRenderFeatureError(
|
|
21
|
+
lastReportedFrame,
|
|
22
|
+
'feature\0plan',
|
|
23
|
+
10 + PENDING_RENDER_FEATURE_ERROR_REPORT_INTERVAL_FRAMES,
|
|
24
|
+
),
|
|
25
|
+
).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('changed render-feature failures', () => {
|
|
30
|
+
it('reports a new cause immediately without flooding repeats', () => {
|
|
31
|
+
const lastReportedFrame = new Map<string, PendingRenderFeatureErrorReport>();
|
|
32
|
+
const reported: RenderError[] = [];
|
|
33
|
+
const registry = { fire: (error: RenderError) => reported.push(error) };
|
|
34
|
+
const failure = (message: string) =>
|
|
35
|
+
new RenderFeatureStageFailedError('recovery', 0, 'plan', 'next-frame', new Error(message));
|
|
36
|
+
reportPendingRenderFeatureErrors([failure('invalid-format')], 1, lastReportedFrame, registry);
|
|
37
|
+
reportPendingRenderFeatureErrors([failure('invalid-format')], 2, lastReportedFrame, registry);
|
|
38
|
+
reportPendingRenderFeatureErrors([failure('cycle')], 3, lastReportedFrame, registry);
|
|
39
|
+
expect(reported).toHaveLength(2);
|
|
40
|
+
reportPendingRenderFeatureErrors([failure('cycle')], 4, lastReportedFrame, registry);
|
|
41
|
+
expect(reported).toHaveLength(2);
|
|
42
|
+
expect(lastReportedFrame.size).toBe(1);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -23,7 +23,16 @@ function feature(mode: 'healthy' | 'failed'): RenderFeature<{ readonly ready: tr
|
|
|
23
23
|
'next-frame',
|
|
24
24
|
),
|
|
25
25
|
)
|
|
26
|
-
: ok({
|
|
26
|
+
: ok({
|
|
27
|
+
resources: [
|
|
28
|
+
{
|
|
29
|
+
kind: 'fullscreen-program' as const,
|
|
30
|
+
name: 'synthetic.diagnostics.program',
|
|
31
|
+
source: 'synthetic',
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
passes: [],
|
|
35
|
+
}),
|
|
27
36
|
};
|
|
28
37
|
}
|
|
29
38
|
|
|
@@ -55,7 +55,17 @@ describe('render feature retry rules', () => {
|
|
|
55
55
|
identity: 'synthetic.capability-retry',
|
|
56
56
|
requiredCapabilities: ['compute'],
|
|
57
57
|
extract: ({ frameNumber }) => ok({ frame: frameNumber }),
|
|
58
|
-
plan: () =>
|
|
58
|
+
plan: () =>
|
|
59
|
+
ok({
|
|
60
|
+
resources: [
|
|
61
|
+
{
|
|
62
|
+
kind: 'fullscreen-program' as const,
|
|
63
|
+
name: 'synthetic.capability-retry.program',
|
|
64
|
+
source: 'synthetic',
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
passes: [],
|
|
68
|
+
}),
|
|
59
69
|
};
|
|
60
70
|
const host = createRenderFeatureHost([feature], caps(false)).unwrap();
|
|
61
71
|
|
|
@@ -65,6 +75,7 @@ describe('render feature retry rules', () => {
|
|
|
65
75
|
frameNumber: 1,
|
|
66
76
|
caps: caps(false),
|
|
67
77
|
});
|
|
78
|
+
expect(host.diagnostics()[0]?.status).toBe('disabled');
|
|
68
79
|
expect(
|
|
69
80
|
runRenderFeatureFrame(host, {
|
|
70
81
|
worlds: [],
|
|
@@ -89,6 +89,29 @@ function frame(host: RenderFeatureHost, frameNumber: number) {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
describe('RenderFeature stage fault recovery lifecycle', () => {
|
|
92
|
+
it('retains the original exception when a feature stage throws', () => {
|
|
93
|
+
const cause = new TypeError('feature plan exploded');
|
|
94
|
+
const host = createRenderFeatureHost(
|
|
95
|
+
[
|
|
96
|
+
{
|
|
97
|
+
identity: 'synthetic.m10.throwing',
|
|
98
|
+
extract: () => ok({ ready: true }),
|
|
99
|
+
plan: () => {
|
|
100
|
+
throw cause;
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
caps,
|
|
105
|
+
).unwrap();
|
|
106
|
+
|
|
107
|
+
const result = frame(host, 1);
|
|
108
|
+
expect(result.errors[0]).toMatchObject({
|
|
109
|
+
code: 'render-feature-stage-failed',
|
|
110
|
+
detail: { featureIdentity: 'synthetic.m10.throwing', cause },
|
|
111
|
+
});
|
|
112
|
+
expect(host.diagnostics()[0]?.latestError).toMatchObject({ detail: { cause } });
|
|
113
|
+
});
|
|
114
|
+
|
|
92
115
|
it.each<Fault>([
|
|
93
116
|
'create',
|
|
94
117
|
'prepared-resource',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssetRegistry, HANDLE_CUBE } from '@forgeax/engine-assets-runtime';
|
|
1
|
+
import { AssetRegistry, HANDLE_CUBE, RuntimeMaterialValue } from '@forgeax/engine-assets-runtime';
|
|
2
2
|
import type { EntityHandle } from '@forgeax/engine-ecs';
|
|
3
3
|
import { World } from '@forgeax/engine-ecs';
|
|
4
4
|
import { createRenderReadLease } from '@forgeax/engine-ecs/projection';
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
Visibility,
|
|
16
16
|
VisibilityStateValue,
|
|
17
17
|
} from '../components';
|
|
18
|
-
import {
|
|
18
|
+
import { InstanceProjectionStore } from '../instances';
|
|
19
19
|
import { type ExtractedFrame, extractFrames } from '../render-system-extract';
|
|
20
20
|
import {
|
|
21
21
|
type PersistentRenderCandidateRequest,
|
|
@@ -47,7 +47,7 @@ function material(values: Record<string, unknown>): MaterialAsset {
|
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
function createWorld(
|
|
50
|
+
function createWorld(withCamera: boolean) {
|
|
51
51
|
const world = new World();
|
|
52
52
|
registerPropagateTransforms(world);
|
|
53
53
|
const values: Record<string, unknown> = {
|
|
@@ -80,7 +80,6 @@ function createWorld(instanceCollections: InstanceCollectionStore, withCamera: b
|
|
|
80
80
|
{ component: Visibility, data: { state: VisibilityStateValue.visible } },
|
|
81
81
|
)
|
|
82
82
|
.unwrap();
|
|
83
|
-
const mixedCollection = instanceCollections.create({ transforms: matrices(2, 0) }).unwrap();
|
|
84
83
|
const mixed = world
|
|
85
84
|
.spawn(
|
|
86
85
|
{ component: Transform, data: { pos: [0, 0, 0] } },
|
|
@@ -88,7 +87,7 @@ function createWorld(instanceCollections: InstanceCollectionStore, withCamera: b
|
|
|
88
87
|
{ component: Visibility, data: { state: VisibilityStateValue.inherited } },
|
|
89
88
|
{ component: MeshFilter, data: { assetHandle: HANDLE_CUBE } },
|
|
90
89
|
{ component: MeshRenderer, data: { materials: [materialHandle] } },
|
|
91
|
-
{ component: Instances, data: {
|
|
90
|
+
{ component: Instances, data: { transforms: matrices(2, 0) } },
|
|
92
91
|
)
|
|
93
92
|
.unwrap();
|
|
94
93
|
const sharedConsumer = world
|
|
@@ -119,7 +118,6 @@ function createWorld(instanceCollections: InstanceCollectionStore, withCamera: b
|
|
|
119
118
|
world,
|
|
120
119
|
values,
|
|
121
120
|
materialHandle,
|
|
122
|
-
mixedCollectionId: mixedCollection.collectionId,
|
|
123
121
|
mixed,
|
|
124
122
|
sharedConsumer,
|
|
125
123
|
hiddenTarget,
|
|
@@ -167,10 +165,59 @@ function rowFor(frame: ExtractedFrame, worldId: number, entityKey: EntityHandle)
|
|
|
167
165
|
}
|
|
168
166
|
|
|
169
167
|
describe('PersistentRenderScene mixed World updates', () => {
|
|
168
|
+
it('publishes instance inspection only with the accepted Scene and retires removed components', () => {
|
|
169
|
+
const { world, mixed } = createWorld(true);
|
|
170
|
+
const instanceCollections = new InstanceProjectionStore();
|
|
171
|
+
const scene = new PersistentRenderScene({ instanceCollections });
|
|
172
|
+
const lease = createRenderReadLease(world);
|
|
173
|
+
const owner = { cameraOwner: 0, resourceOwner: 0 };
|
|
174
|
+
let rejectCandidate = false;
|
|
175
|
+
const build = (request: PersistentRenderCandidateRequest) => {
|
|
176
|
+
const frame = extractFrames([world], owner, undefined, undefined, undefined, {
|
|
177
|
+
cull: 'none',
|
|
178
|
+
retainHidden: true,
|
|
179
|
+
renderables: request,
|
|
180
|
+
instanceCollections,
|
|
181
|
+
});
|
|
182
|
+
if (rejectCandidate && request !== 'none') throw new Error('reject prepared candidate');
|
|
183
|
+
return frame;
|
|
184
|
+
};
|
|
185
|
+
const draw = () => scene.extractComposition([world], owner, 0, build, [lease]);
|
|
186
|
+
try {
|
|
187
|
+
draw();
|
|
188
|
+
const before = instanceCollections._inspections(0);
|
|
189
|
+
expect(before).toHaveLength(1);
|
|
190
|
+
world.set(mixed, Instances, { transforms: matrices(3, 9) }).unwrap();
|
|
191
|
+
rejectCandidate = true;
|
|
192
|
+
expect(draw).toThrow('reject prepared candidate');
|
|
193
|
+
expect(instanceCollections._inspections(0)).toEqual(before);
|
|
194
|
+
rejectCandidate = false;
|
|
195
|
+
expect(rowFor(draw(), 0, mixed)?.instances?.instanceCount).toBe(3);
|
|
196
|
+
expect(instanceCollections._inspections(0)[0]?.revision).toBe((before[0]?.revision ?? 0) + 1);
|
|
197
|
+
world.removeComponent(mixed, Instances).unwrap();
|
|
198
|
+
draw();
|
|
199
|
+
expect(instanceCollections._inspections(0)).toEqual([]);
|
|
200
|
+
world
|
|
201
|
+
.addComponent(mixed, { component: Instances, data: { transforms: matrices(1, 2) } })
|
|
202
|
+
.unwrap();
|
|
203
|
+
draw();
|
|
204
|
+
expect(instanceCollections._inspections(0)[0]?.collectionId).not.toBe(
|
|
205
|
+
before[0]?.collectionId,
|
|
206
|
+
);
|
|
207
|
+
world.despawn(mixed).unwrap();
|
|
208
|
+
draw();
|
|
209
|
+
expect(instanceCollections._inspections(0)).toEqual([]);
|
|
210
|
+
} finally {
|
|
211
|
+
lease.dispose();
|
|
212
|
+
scene.dispose();
|
|
213
|
+
instanceCollections.dispose();
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
170
217
|
it('reconciles mixed fields against a fresh extract while retaining other slot history', () => {
|
|
171
|
-
const instanceCollections = new
|
|
172
|
-
const first = createWorld(
|
|
173
|
-
const second = createWorld(
|
|
218
|
+
const instanceCollections = new InstanceProjectionStore();
|
|
219
|
+
const first = createWorld(true);
|
|
220
|
+
const second = createWorld(false);
|
|
174
221
|
const worlds = [first.world, second.world] as const;
|
|
175
222
|
const leases = [
|
|
176
223
|
createRenderReadLease(first.world),
|
|
@@ -226,15 +273,24 @@ describe('PersistentRenderScene mixed World updates', () => {
|
|
|
226
273
|
expect(initialOtherWorld).toBeDefined();
|
|
227
274
|
|
|
228
275
|
requests.length = 0;
|
|
229
|
-
|
|
276
|
+
first.world.set(first.mixed, Instances, { transforms: matrices(3, 2) }).unwrap();
|
|
230
277
|
first.world.set(first.mixed, Transform, { pos: [0.25, 0, 0] }).unwrap();
|
|
231
278
|
first.world.set(first.mixed, ChildOf, { parent: first.parentB }).unwrap();
|
|
232
279
|
first.world.set(first.parentA, Visibility, { state: VisibilityStateValue.hidden }).unwrap();
|
|
233
280
|
first.world
|
|
234
281
|
.set(first.hiddenTarget, Visibility, { state: VisibilityStateValue.hidden })
|
|
235
282
|
.unwrap();
|
|
236
|
-
first.
|
|
237
|
-
|
|
283
|
+
first.world
|
|
284
|
+
.spawn({
|
|
285
|
+
component: RuntimeMaterialValue,
|
|
286
|
+
data: {
|
|
287
|
+
asset: first.materialHandle,
|
|
288
|
+
parameter: 'baseColor',
|
|
289
|
+
kind: 2,
|
|
290
|
+
value: [0, 1, 0, 1],
|
|
291
|
+
},
|
|
292
|
+
})
|
|
293
|
+
.unwrap();
|
|
238
294
|
first.world.update(0).unwrap();
|
|
239
295
|
|
|
240
296
|
const mixed = draw();
|
|
@@ -264,7 +320,7 @@ describe('PersistentRenderScene mixed World updates', () => {
|
|
|
264
320
|
submit(mixed);
|
|
265
321
|
|
|
266
322
|
requests.length = 0;
|
|
267
|
-
|
|
323
|
+
first.world.set(first.mixed, Instances, { transforms: matrices(0, 0) }).unwrap();
|
|
268
324
|
first.world.update(0).unwrap();
|
|
269
325
|
const zero = draw();
|
|
270
326
|
expect(frameFacts(zero)).toEqual(frameFacts(drawableOracle()));
|
|
@@ -274,7 +330,7 @@ describe('PersistentRenderScene mixed World updates', () => {
|
|
|
274
330
|
submit(zero);
|
|
275
331
|
|
|
276
332
|
requests.length = 0;
|
|
277
|
-
|
|
333
|
+
first.world.set(first.mixed, Instances, { transforms: matrices(1, -2) }).unwrap();
|
|
278
334
|
first.world.update(0).unwrap();
|
|
279
335
|
const one = draw();
|
|
280
336
|
expect(frameFacts(one)).toEqual(frameFacts(drawableOracle()));
|
|
@@ -290,9 +346,9 @@ describe('PersistentRenderScene mixed World updates', () => {
|
|
|
290
346
|
});
|
|
291
347
|
|
|
292
348
|
it('retains slot and temporal history across World reorder and catalog refresh', () => {
|
|
293
|
-
const instanceCollections = new
|
|
294
|
-
const first = createWorld(
|
|
295
|
-
const second = createWorld(
|
|
349
|
+
const instanceCollections = new InstanceProjectionStore();
|
|
350
|
+
const first = createWorld(true);
|
|
351
|
+
const second = createWorld(false);
|
|
296
352
|
let worlds: readonly World[] = [first.world, second.world];
|
|
297
353
|
let leases = [createRenderReadLease(first.world), createRenderReadLease(second.world)];
|
|
298
354
|
let owner = { cameraOwner: 0, resourceOwner: 0 };
|
|
@@ -373,8 +429,8 @@ describe('PersistentRenderScene mixed World updates', () => {
|
|
|
373
429
|
});
|
|
374
430
|
|
|
375
431
|
it('scopes parent and leaf visibility changes while preserving unrelated snapshots', () => {
|
|
376
|
-
const instanceCollections = new
|
|
377
|
-
const first = createWorld(
|
|
432
|
+
const instanceCollections = new InstanceProjectionStore();
|
|
433
|
+
const first = createWorld(true);
|
|
378
434
|
const lease = createRenderReadLease(first.world);
|
|
379
435
|
const scene = new PersistentRenderScene({ instanceCollections });
|
|
380
436
|
const assets = new AssetRegistry({
|
|
@@ -424,3 +480,73 @@ describe('PersistentRenderScene mixed World updates', () => {
|
|
|
424
480
|
}
|
|
425
481
|
});
|
|
426
482
|
});
|
|
483
|
+
|
|
484
|
+
it('two Renderers independently observe shared content replacement, rebinding, deletion and retry', () => {
|
|
485
|
+
const fixture = createWorld(true);
|
|
486
|
+
const { world, materialHandle, sharedConsumer } = fixture;
|
|
487
|
+
const owner = { cameraOwner: 0, resourceOwner: 0 };
|
|
488
|
+
const assets = new AssetRegistry({
|
|
489
|
+
findMaterialArtifact: () => ({ ok: false, error: new Error('not registered') }),
|
|
490
|
+
} as unknown as ShaderRegistry);
|
|
491
|
+
const consumers = [0, 1].map(() => {
|
|
492
|
+
const instanceCollections = new InstanceProjectionStore();
|
|
493
|
+
const scene = new PersistentRenderScene({ instanceCollections });
|
|
494
|
+
const lease = createRenderReadLease(world);
|
|
495
|
+
let fail = false;
|
|
496
|
+
const build = (request: PersistentRenderCandidateRequest) => {
|
|
497
|
+
if (fail) {
|
|
498
|
+
fail = false;
|
|
499
|
+
throw new Error('injected extraction failure');
|
|
500
|
+
}
|
|
501
|
+
return extractFrames([world], owner, assets, undefined, scene.materialSnapshotCacheStore(), {
|
|
502
|
+
cull: 'none',
|
|
503
|
+
retainHidden: true,
|
|
504
|
+
renderables: request,
|
|
505
|
+
instanceCollections,
|
|
506
|
+
});
|
|
507
|
+
};
|
|
508
|
+
return {
|
|
509
|
+
scene,
|
|
510
|
+
lease,
|
|
511
|
+
draw: () => scene.extractComposition([world], owner, 0, build, [lease]),
|
|
512
|
+
fail: () => {
|
|
513
|
+
fail = true;
|
|
514
|
+
},
|
|
515
|
+
};
|
|
516
|
+
});
|
|
517
|
+
const color = (frame: ExtractedFrame) =>
|
|
518
|
+
Array.from(rowFor(frame, 0, sharedConsumer)?.material.baseColor ?? []);
|
|
519
|
+
try {
|
|
520
|
+
for (const consumer of consumers) expect(color(consumer.draw())).toEqual([1, 0, 0]);
|
|
521
|
+
const content = world
|
|
522
|
+
.spawn({
|
|
523
|
+
component: RuntimeMaterialValue,
|
|
524
|
+
data: {
|
|
525
|
+
asset: materialHandle,
|
|
526
|
+
parameter: 'baseColor',
|
|
527
|
+
kind: 2,
|
|
528
|
+
value: [0, 1, 0, 1],
|
|
529
|
+
},
|
|
530
|
+
})
|
|
531
|
+
.unwrap();
|
|
532
|
+
for (const consumer of consumers) {
|
|
533
|
+
consumer.fail();
|
|
534
|
+
expect(() => consumer.draw()).toThrow('injected extraction failure');
|
|
535
|
+
expect(color(consumer.draw())).toEqual([0, 1, 0]);
|
|
536
|
+
}
|
|
537
|
+
const other = world.allocSharedRef('MaterialAsset', material({ baseColor: [0, 0, 1, 1] }));
|
|
538
|
+
world.set(content, RuntimeMaterialValue, { asset: other }).unwrap();
|
|
539
|
+
for (const consumer of consumers) expect(color(consumer.draw())).toEqual([1, 0, 0]);
|
|
540
|
+
world
|
|
541
|
+
.set(content, RuntimeMaterialValue, { asset: materialHandle, value: [0, 0, 1, 1] })
|
|
542
|
+
.unwrap();
|
|
543
|
+
for (const consumer of consumers) expect(color(consumer.draw())).toEqual([0, 0, 1]);
|
|
544
|
+
world.despawn(content).unwrap();
|
|
545
|
+
for (const consumer of consumers) expect(color(consumer.draw())).toEqual([1, 0, 0]);
|
|
546
|
+
} finally {
|
|
547
|
+
for (const consumer of consumers) {
|
|
548
|
+
consumer.lease.dispose();
|
|
549
|
+
consumer.scene.dispose();
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
});
|