@forgeax/engine-render 0.1.33 → 0.1.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1010 -124
- package/dist/assembly/backend-contract.d.ts +2 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -1
- package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
- package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
- package/dist/assembly/canvas-draw-guard.d.ts +3 -0
- package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
- package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
- package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
- package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
- package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
- package/dist/assembly/factory.d.ts +1 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +3 -3
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
- package/dist/assembly/material-shader-policy.d.ts +16 -2
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/render-feature-post-processes.d.ts +6 -0
- package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
- package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-inspection.d.ts +11 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -1
- package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
- package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +1 -1
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
- package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/barrel-distortion.d.ts +47 -0
- package/dist/barrel-distortion.d.ts.map +1 -0
- package/dist/{chunk-PA5DRJNI.mjs → chunk-ELJFJ2BU.mjs} +2 -2
- package/dist/chunk-ELJFJ2BU.mjs.map +1 -0
- package/dist/{chunk-ZDQWGQW7.mjs → chunk-HEB564WF.mjs} +4 -4
- package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-HEB564WF.mjs.map} +1 -1
- package/dist/{chunk-VOZWDM3L.mjs → chunk-MKDIT2EM.mjs} +1307 -188
- package/dist/chunk-MKDIT2EM.mjs.map +1 -0
- package/dist/{chunk-LEAXOMYJ.mjs → chunk-OCDLEI6I.mjs} +3 -3
- package/dist/{chunk-LEAXOMYJ.mjs.map → chunk-OCDLEI6I.mjs.map} +1 -1
- package/dist/chunk-ODZWR6JQ.mjs +4927 -0
- package/dist/chunk-ODZWR6JQ.mjs.map +1 -0
- package/dist/{chunk-3RTCJTH4.mjs → chunk-SHFUFJ5N.mjs} +184 -13
- package/dist/chunk-SHFUFJ5N.mjs.map +1 -0
- package/dist/{chunk-OO3DRYK7.mjs → chunk-UI5SFODX.mjs} +176 -96
- package/dist/chunk-UI5SFODX.mjs.map +1 -0
- package/dist/{chunk-PLAXOOX5.mjs → chunk-UINHLCZA.mjs} +561 -79
- package/dist/chunk-UINHLCZA.mjs.map +1 -0
- package/dist/{chunk-NB2S7ZRX.mjs → chunk-WEX45HKH.mjs} +127 -386
- package/dist/chunk-WEX45HKH.mjs.map +1 -0
- package/dist/cloud/density.d.ts +55 -0
- package/dist/cloud/density.d.ts.map +1 -0
- package/dist/cloud/extract.d.ts +25 -0
- package/dist/cloud/extract.d.ts.map +1 -0
- package/dist/cloud/feature.d.ts +57 -0
- package/dist/cloud/feature.d.ts.map +1 -0
- package/dist/cloud/frame-context.d.ts +8 -0
- package/dist/cloud/frame-context.d.ts.map +1 -0
- package/dist/cloud/inspection.d.ts +59 -0
- package/dist/cloud/inspection.d.ts.map +1 -0
- package/dist/cloud/optics.d.ts +56 -0
- package/dist/cloud/optics.d.ts.map +1 -0
- package/dist/cloud/parameters.d.ts +73 -0
- package/dist/cloud/parameters.d.ts.map +1 -0
- package/dist/cloud/resources.d.ts +60 -0
- package/dist/cloud/resources.d.ts.map +1 -0
- package/dist/cloud/shadow.d.ts +42 -0
- package/dist/cloud/shadow.d.ts.map +1 -0
- package/dist/cloud/temporal.d.ts +74 -0
- package/dist/cloud/temporal.d.ts.map +1 -0
- package/dist/components/barrel-distortion.d.ts +13 -0
- package/dist/components/barrel-distortion.d.ts.map +1 -0
- package/dist/components/cloud-layer.d.ts +29 -0
- package/dist/components/cloud-layer.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +20 -6
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/construct-renderer.d.ts +1 -1
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +6759 -2875
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/dynamic-geometry.d.ts +5 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/errors/cloud.d.ts +59 -0
- package/dist/errors/cloud.d.ts.map +1 -0
- package/dist/errors/render.d.ts +18 -4
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/examples/single-layer-medium-surface.d.ts +47 -0
- package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +5 -1
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/features/barrel-distortion.d.ts +29 -0
- package/dist/features/barrel-distortion.d.ts.map +1 -0
- package/dist/features/error-reporting.d.ts +6 -2
- package/dist/features/error-reporting.d.ts.map +1 -1
- package/dist/features/host.d.ts +10 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/plan.d.ts +8 -0
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +5 -0
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +1 -0
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/targets.d.ts +2 -0
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +44 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +15 -7
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-dirty-ranges.d.ts +11 -0
- package/dist/gpu-dirty-ranges.d.ts.map +1 -0
- package/dist/gpu-driven/batch-topology.d.ts +17 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts +6 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster-material.d.ts +178 -0
- package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +47 -3
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/resource-allocation.d.ts +31 -0
- package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
- package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
- package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +26 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +5 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +2 -2
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +10 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +27 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +258 -8
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +135 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instance-buffer-cache.d.ts +4 -4
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +48 -100
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +7 -7
- package/dist/pbr-pipeline.d.ts +19 -1
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
- package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
- package/dist/pipeline/standard-output/types.d.ts +4 -2
- package/dist/pipeline/standard-output/types.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/record/barrel-distortion-frame.d.ts +15 -0
- package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
- package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
- package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
- package/dist/record/fold-buckets.d.ts +95 -0
- package/dist/record/fold-buckets.d.ts.map +1 -0
- package/dist/record/fold-instance-buffer.d.ts +6 -0
- package/dist/record/fold-instance-buffer.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +1 -0
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +37 -3
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +10 -61
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-draw-receipts.d.ts +11 -0
- package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +8 -0
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +21 -5
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +13 -2
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/motion-blur-receipt.d.ts +11 -0
- package/dist/record/motion-blur-receipt.d.ts.map +1 -0
- package/dist/record/probe-blend-buffer.d.ts +16 -0
- package/dist/record/probe-blend-buffer.d.ts.map +1 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +22 -3
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -0
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +22 -2
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +11 -3
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/record/volume-params.d.ts +9 -0
- package/dist/record/volume-params.d.ts.map +1 -0
- package/dist/recovery/render-system-candidate.d.ts +10 -0
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +42 -4
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +103 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +3 -2
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +16 -9
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-presentation.d.ts +23 -0
- package/dist/render-system-presentation.d.ts.map +1 -0
- package/dist/render-system-producer-roots.d.ts +10 -0
- package/dist/render-system-producer-roots.d.ts.map +1 -0
- package/dist/render-system-residency.d.ts +12 -0
- package/dist/render-system-residency.d.ts.map +1 -0
- package/dist/render-system.d.ts +19 -14
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/probe-blend.d.ts +27 -0
- package/dist/scene/probe-blend.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +12 -5
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +9 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/surface/dynamic-input.d.ts +133 -0
- package/dist/surface/dynamic-input.d.ts.map +1 -0
- package/dist/surface/gpu-driven.d.ts +41 -0
- package/dist/surface/gpu-driven.d.ts.map +1 -0
- package/dist/surface/submission-observation.d.ts +136 -0
- package/dist/surface/submission-observation.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts +13 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- package/dist/temporal/inspection.d.ts.map +1 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
- package/dist/transmission/single-layer-medium.d.ts +89 -0
- package/dist/transmission/single-layer-medium.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +14 -2
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +9 -4
- package/dist/volume/component.d.ts.map +1 -1
- package/dist/volume/extract.d.ts +1 -1
- package/dist/volume/extract.d.ts.map +1 -1
- package/dist/volume/inspection.d.ts +2 -0
- package/dist/volume/inspection.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +4 -1
- package/dist/volume/passes.d.ts.map +1 -1
- package/dist/volume/resources.d.ts.map +1 -1
- package/package.json +22 -21
- package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
- package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
- package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
- package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
- package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
- package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
- package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
- package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
- package/src/__tests__/factory-contract.integration.test.ts +295 -45
- package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
- package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
- package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +2 -2
- package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
- package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
- package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
- package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
- package/src/__tests__/gpu-scene.unit.test.ts +119 -9
- package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
- package/src/__tests__/instances-culling.integration.test.ts +10 -36
- package/src/__tests__/instances-store.unit.test.ts +97 -305
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +146 -0
- package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
- package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
- package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
- package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
- package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +58 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
- package/src/__tests__/probe-bindings.unit.test.ts +582 -1
- package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
- package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +7 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
- package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
- package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
- package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
- package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
- package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
- package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
- package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +41 -7
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
- package/src/__tests__/resource-allocation.unit.test.ts +123 -0
- package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
- package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
- package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
- package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
- package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
- package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
- package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
- package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
- package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
- package/src/__tests__/temporal-performance.integration.test.ts +3 -3
- package/src/__tests__/visibility-instances.integration.test.ts +7 -19
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
- package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
- package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
- package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
- package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
- package/src/assembly/backend-contract.ts +30 -0
- package/src/assembly/barrel-distortion-inspection.ts +22 -0
- package/src/assembly/canvas-draw-guard.ts +11 -0
- package/src/assembly/cloud-shadow-entry.ts +22 -0
- package/src/assembly/dynamic-geometry-host.ts +65 -37
- package/src/assembly/dynamic-geometry-runtime.ts +7 -1
- package/src/assembly/factory.ts +2 -30
- package/src/assembly/host-contract.ts +3 -3
- package/src/assembly/material/assembly.ts +25 -13
- package/src/assembly/material/pipeline-helpers.ts +53 -12
- package/src/assembly/material-shader-policy.ts +55 -0
- package/src/assembly/material-shader-prewarm.ts +21 -10
- package/src/assembly/recovery/device-loss-fanout.ts +13 -0
- package/src/assembly/recovery/renderer-recover.ts +41 -18
- package/src/assembly/render-feature-post-processes.ts +54 -0
- package/src/assembly/renderer-facade.ts +4 -1
- package/src/assembly/renderer-feature-inspection.ts +8 -2
- package/src/assembly/renderer-frame-transaction.ts +23 -0
- package/src/assembly/renderer-inspection.ts +28 -0
- package/src/assembly/skin-palette-owner.ts +1 -1
- package/src/assembly/temporal-post-process-prewarm.ts +3 -3
- package/src/assembly/webgpu-pbr-ready.ts +9 -1
- package/src/assembly/webgpu-ready-per-pass.ts +104 -0
- package/src/assembly/webgpu-ready.ts +115 -61
- package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
- package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
- package/src/assembly/webgpu-renderer.ts +214 -252
- package/src/assembly/webgpu-vertex-layouts.ts +1 -1
- package/src/barrel-distortion.ts +247 -0
- package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
- package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
- package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
- package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
- package/src/cloud/density.ts +600 -0
- package/src/cloud/extract.ts +110 -0
- package/src/cloud/feature.ts +1810 -0
- package/src/cloud/frame-context.ts +42 -0
- package/src/cloud/inspection.ts +130 -0
- package/src/cloud/optics.ts +285 -0
- package/src/cloud/parameters.ts +255 -0
- package/src/cloud/resources.ts +122 -0
- package/src/cloud/shadow.ts +167 -0
- package/src/cloud/temporal.ts +226 -0
- package/src/components/barrel-distortion.ts +46 -0
- package/src/components/cloud-layer.ts +47 -0
- package/src/components/index.ts +2 -0
- package/src/components/instances.ts +18 -45
- package/src/components/sprite-instances.ts +1 -1
- package/src/construct-renderer.ts +1 -1
- package/src/dynamic-geometry.ts +12 -1
- package/src/errors/cloud.ts +103 -0
- package/src/errors/render.ts +44 -7
- package/src/examples/single-layer-medium-surface.ts +59 -0
- package/src/extract/camera.ts +15 -1
- package/src/extract/contracts.ts +5 -0
- package/src/features/barrel-distortion.ts +172 -0
- package/src/features/error-reporting.ts +26 -6
- package/src/features/host.ts +115 -14
- package/src/features/plan.ts +8 -0
- package/src/features/render-graph-contribution.ts +9 -0
- package/src/features/render-graph-raster.ts +45 -3
- package/src/features/targets.ts +66 -0
- package/src/features/types.ts +47 -0
- package/src/fullscreen-post-process-pass.ts +41 -9
- package/src/gpu-dirty-ranges.ts +48 -0
- package/src/gpu-driven/batch-topology.ts +53 -0
- package/src/gpu-driven/material-artifacts.ts +33 -25
- package/src/gpu-driven/prepared-draw.ts +12 -4
- package/src/gpu-driven/production-raster-material.ts +1894 -0
- package/src/gpu-driven/production-raster.ts +825 -784
- package/src/gpu-driven/resource-allocation.ts +142 -0
- package/src/gpu-driven/shadow-ownership.ts +71 -0
- package/src/gpu-driven/view-gpu.ts +164 -10
- package/src/gpu-scene.ts +75 -84
- package/src/hdrp-buffers.ts +4 -3
- package/src/ibl/skylight-bind-group.ts +49 -7
- package/src/index.ts +196 -9
- package/src/inspection-types.ts +162 -0
- package/src/instance-buffer-cache.ts +4 -4
- package/src/instances.ts +149 -569
- package/src/pbr-pipeline.ts +219 -13
- package/src/pipeline/single-layer-medium-passes.ts +267 -0
- package/src/pipeline/standard-forward-lane.ts +313 -57
- package/src/pipeline/standard-output/graph.ts +8 -2
- package/src/pipeline/standard-output/types.ts +12 -1
- package/src/pipeline/standard-pipeline.ts +291 -18
- package/src/pipeline/standard-post.ts +90 -24
- package/src/pipeline-builder.ts +1 -1
- package/src/plugin.ts +4 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
- package/src/prepare/prepared-graphics-resolver.ts +2 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +1 -1
- package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
- package/src/record/barrel-distortion-frame.ts +110 -0
- package/src/record/dynamic-geometry-consumption.ts +39 -9
- package/src/record/fold-buckets.ts +852 -0
- package/src/record/fold-instance-buffer.ts +51 -0
- package/src/record/frame-lighting.ts +36 -2
- package/src/record/frame-snapshot.ts +39 -3
- package/src/record/frame.ts +217 -1084
- package/src/record/gpu-draw-receipts.ts +38 -0
- package/src/record/gpu-timing.ts +48 -5
- package/src/record/main-pass-geometry.ts +251 -82
- package/src/record/main-pass-material.ts +66 -4
- package/src/record/main-pass-sprite-draws.ts +7 -65
- package/src/record/main-pass.ts +156 -20
- package/src/record/motion-blur-receipt.ts +91 -0
- package/src/record/probe-blend-buffer.ts +180 -0
- package/src/record/recovery-pipeline.ts +35 -3
- package/src/record/render-context.ts +39 -3
- package/src/record/shadow-pass.ts +30 -1
- package/src/record/skybox-post-pass.ts +28 -4
- package/src/record/typed-frame-graph.ts +770 -134
- package/src/record/view-ubo.ts +26 -3
- package/src/record/volume-params.ts +225 -0
- package/src/recovery/render-system-candidate.ts +235 -42
- package/src/reflection/record-owner.ts +7 -3
- package/src/render-contract.ts +48 -4
- package/src/render-graph-primitives.ts +7 -1
- package/src/render-pipeline.ts +130 -0
- package/src/render-system-extract-tail.ts +57 -61
- package/src/render-system-extract.ts +74 -76
- package/src/render-system-presentation.ts +56 -0
- package/src/render-system-producer-roots.ts +96 -0
- package/src/render-system-residency.ts +159 -0
- package/src/render-system.ts +347 -363
- package/src/scene/probe-blend.ts +96 -4
- package/src/scene/render-scene.ts +349 -280
- package/src/ssao-buffers.ts +95 -2
- package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
- package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
- package/src/surface/dynamic-input.ts +658 -0
- package/src/surface/gpu-driven.ts +147 -0
- package/src/surface/submission-observation.ts +517 -0
- package/src/systems/skin-palette-allocator.ts +4 -1
- package/src/temporal/gpu.ts +101 -17
- package/src/temporal/inspection.ts +7 -1
- package/src/temporal/standard-scene-data.ts +5 -0
- package/src/temporal/target-coverage-attachment.ts +4 -0
- package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
- package/src/transmission/single-layer-medium.ts +322 -0
- package/src/typed-render-graph-primitives.ts +70 -2
- package/src/volume/component.ts +10 -9
- package/src/volume/extract.ts +11 -5
- package/src/volume/inspection.ts +3 -0
- package/src/volume/passes.ts +87 -4
- package/src/volume/resources.ts +2 -1
- package/dist/chunk-3RTCJTH4.mjs.map +0 -1
- package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
- package/dist/chunk-NNQL7CB3.mjs +0 -1713
- package/dist/chunk-NNQL7CB3.mjs.map +0 -1
- package/dist/chunk-OO3DRYK7.mjs.map +0 -1
- package/dist/chunk-PA5DRJNI.mjs.map +0 -1
- package/dist/chunk-PLAXOOX5.mjs.map +0 -1
- package/dist/chunk-VOZWDM3L.mjs.map +0 -1
|
@@ -7,8 +7,13 @@ import { BatchTopology } from '../gpu-driven/batch-topology';
|
|
|
7
7
|
import { GPU_DRIVEN_VIEW_WGSL, GpuDrivenView } from '../gpu-driven/view-gpu';
|
|
8
8
|
import { GpuScene } from '../gpu-scene';
|
|
9
9
|
import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_MAP_READ } from '../gpu-usage';
|
|
10
|
+
import { getOpaqueResourceIdentity } from '../record/frame-snapshot';
|
|
10
11
|
import type { MaterialSnapshot, RenderableSnapshot } from '../render-system-extract';
|
|
11
12
|
import { RenderScene } from '../scene/render-scene';
|
|
13
|
+
import {
|
|
14
|
+
type SurfaceSubmissionCandidate,
|
|
15
|
+
SurfaceSubmissionObservationOwner,
|
|
16
|
+
} from '../surface/submission-observation';
|
|
12
17
|
|
|
13
18
|
const GPU_MAP_MODE_READ = 0x0001;
|
|
14
19
|
|
|
@@ -62,6 +67,10 @@ export interface GpuDrivenViewGpuEvidence {
|
|
|
62
67
|
readonly firstInstance: number;
|
|
63
68
|
readonly overflow: number;
|
|
64
69
|
readonly persistentTranslationX: number;
|
|
70
|
+
readonly firstReadbackFrame: number;
|
|
71
|
+
readonly recoveredReadbackFrame: number;
|
|
72
|
+
readonly firstVisible: number;
|
|
73
|
+
readonly recoveredVisible: number;
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
export interface GpuDrivenViewLifecycleEvidence {
|
|
@@ -71,7 +80,7 @@ export interface GpuDrivenViewLifecycleEvidence {
|
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
export async function runGpuDrivenViewLifecycleEvidence(
|
|
74
|
-
frames =
|
|
83
|
+
frames = 60,
|
|
75
84
|
): Promise<GpuDrivenViewLifecycleEvidence> {
|
|
76
85
|
const adapter = (await rhi.requestAdapter()).unwrap();
|
|
77
86
|
const device = (await adapter.requestDevice()).unwrap();
|
|
@@ -247,8 +256,27 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
|
|
|
247
256
|
})
|
|
248
257
|
.unwrap();
|
|
249
258
|
const graph = new RenderGraphBuilder<{ readonly encoder: RhiCommandEncoder }>();
|
|
259
|
+
const submissionOwner = new SurfaceSubmissionObservationOwner(() => 1);
|
|
260
|
+
const beginSubmission = (frameId: number, indirectOffset: number): SurfaceSubmissionCandidate => {
|
|
261
|
+
const candidate = submissionOwner.begin({
|
|
262
|
+
frameId,
|
|
263
|
+
requestedLane: 'gpu-driven',
|
|
264
|
+
deviceGeneration: 1,
|
|
265
|
+
resourceGeneration: view.inspect().resourceGeneration,
|
|
266
|
+
});
|
|
267
|
+
for (const pass of ['nearest-layer', 'color'] as const) {
|
|
268
|
+
candidate.record(pass, {
|
|
269
|
+
kind: 'draw-indexed-indirect',
|
|
270
|
+
indirectBufferIdentity: getOpaqueResourceIdentity(indirect as object),
|
|
271
|
+
indirectOffset,
|
|
272
|
+
pipelineIdentity: 33,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
return candidate;
|
|
276
|
+
};
|
|
277
|
+
let currentSubmission = beginSubmission(10, 0);
|
|
250
278
|
view.setTelemetrySubmit({ frameId: 1, deviceGeneration: 0 });
|
|
251
|
-
view.addPasses(graph).unwrap();
|
|
279
|
+
view.addPasses(graph, 'gpu-driven', true, () => currentSubmission).unwrap();
|
|
252
280
|
const compiled = graph.compile({ device, surfaceSize: { width: 1, height: 1 } }).unwrap();
|
|
253
281
|
const encoder = device.createCommandEncoder({ label: 'gpu-driven-evidence' }).unwrap();
|
|
254
282
|
compiled.execute({ encoder }).unwrap();
|
|
@@ -263,6 +291,7 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
|
|
|
263
291
|
64,
|
|
264
292
|
);
|
|
265
293
|
device.queue.submit([encoder.finish().unwrap()]).unwrap();
|
|
294
|
+
currentSubmission.submit(device.queue.onSubmittedWorkDone(), 1);
|
|
266
295
|
|
|
267
296
|
// Start observing immediately, then submit the cached graph again before
|
|
268
297
|
// the first mapAsync settles. The second copy must be skipped while the
|
|
@@ -277,10 +306,43 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
|
|
|
277
306
|
compiled.execute({ encoder: overlappingEncoder }).unwrap();
|
|
278
307
|
device.queue.submit([overlappingEncoder.finish().unwrap()]).unwrap();
|
|
279
308
|
const lodSelection = await pendingLodSelection;
|
|
280
|
-
if (lodSelection === undefined
|
|
309
|
+
if (lodSelection === undefined) {
|
|
281
310
|
throw new Error('GPU-driven LOD selection readback unavailable or incomplete');
|
|
282
311
|
}
|
|
283
|
-
if (lodSelection.
|
|
312
|
+
if (lodSelection.batches.length !== lodSelection.batchCount) {
|
|
313
|
+
throw new Error('GPU-driven LOD selection readback unavailable or incomplete');
|
|
314
|
+
}
|
|
315
|
+
const surfaceIndirectParameters = lodSelection.surfaceIndirectParameters;
|
|
316
|
+
if (surfaceIndirectParameters === undefined || surfaceIndirectParameters.length !== 2) {
|
|
317
|
+
throw new Error('GPU-driven Surface indirect parameter readback unavailable');
|
|
318
|
+
}
|
|
319
|
+
const firstSurfaceCommand = surfaceIndirectParameters[0];
|
|
320
|
+
if (
|
|
321
|
+
firstSurfaceCommand === undefined ||
|
|
322
|
+
firstSurfaceCommand.sequence !== lodSelection.surfaceReadback?.sequence ||
|
|
323
|
+
firstSurfaceCommand.frameId !== lodSelection.surfaceReadback?.frameId ||
|
|
324
|
+
firstSurfaceCommand.deviceGeneration !== lodSelection.surfaceReadback?.deviceGeneration ||
|
|
325
|
+
firstSurfaceCommand.resourceGeneration !== lodSelection.surfaceReadback?.resourceGeneration ||
|
|
326
|
+
firstSurfaceCommand.pass !== 'nearest-layer' ||
|
|
327
|
+
firstSurfaceCommand.indirectOffset !== 0 ||
|
|
328
|
+
firstSurfaceCommand.count !== 12 ||
|
|
329
|
+
firstSurfaceCommand.instanceCount !== 1 ||
|
|
330
|
+
firstSurfaceCommand.first !== 9 ||
|
|
331
|
+
firstSurfaceCommand.baseVertex !== 4 ||
|
|
332
|
+
firstSurfaceCommand.firstInstance !== 0
|
|
333
|
+
) {
|
|
334
|
+
throw new Error(
|
|
335
|
+
`GPU-driven Surface indirect parameters do not match the submitted batch: ${JSON.stringify({
|
|
336
|
+
firstSurfaceCommand,
|
|
337
|
+
surfaceReadback: lodSelection.surfaceReadback,
|
|
338
|
+
})}`,
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
if (
|
|
342
|
+
lodSelection.submit === undefined ||
|
|
343
|
+
lodSelection.submit.frameId !== 1 ||
|
|
344
|
+
lodSelection.submit.deviceGeneration !== 0
|
|
345
|
+
) {
|
|
284
346
|
throw new Error('GPU-driven LOD telemetry lost the copy submit identity');
|
|
285
347
|
}
|
|
286
348
|
await device.queue.onSubmittedWorkDone();
|
|
@@ -300,23 +362,45 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
|
|
|
300
362
|
const recoveryEncoder = device
|
|
301
363
|
.createCommandEncoder({ label: 'gpu-driven-evidence-recovery' })
|
|
302
364
|
.unwrap();
|
|
365
|
+
currentSubmission = beginSubmission(11, 32);
|
|
303
366
|
compiled.execute({ encoder: recoveryEncoder }).unwrap();
|
|
304
367
|
device.queue.submit([recoveryEncoder.finish().unwrap()]).unwrap();
|
|
368
|
+
currentSubmission.submit(device.queue.onSubmittedWorkDone(), 1);
|
|
305
369
|
await device.queue.onSubmittedWorkDone();
|
|
306
370
|
const recoveredLodSelection = await view.readLodSelection();
|
|
307
371
|
if (
|
|
308
372
|
recoveredLodSelection === undefined ||
|
|
309
373
|
recoveredLodSelection === lodSelection ||
|
|
310
|
-
recoveredLodSelection.visible === lodSelection.visible
|
|
374
|
+
recoveredLodSelection.visible === lodSelection.visible ||
|
|
375
|
+
lodSelection.surfaceReadback?.frameId !== 10 ||
|
|
376
|
+
recoveredLodSelection.surfaceReadback?.frameId !== 11
|
|
311
377
|
) {
|
|
312
378
|
throw new Error('GPU-driven LOD telemetry did not recover after a skipped copy');
|
|
313
379
|
}
|
|
314
380
|
if (
|
|
315
|
-
recoveredLodSelection.
|
|
381
|
+
recoveredLodSelection.surfaceIndirectParameters?.some(
|
|
382
|
+
(command) =>
|
|
383
|
+
command.sequence !== recoveredLodSelection.surfaceReadback?.sequence ||
|
|
384
|
+
command.frameId !== recoveredLodSelection.surfaceReadback?.frameId ||
|
|
385
|
+
command.deviceGeneration !== recoveredLodSelection.surfaceReadback?.deviceGeneration ||
|
|
386
|
+
command.resourceGeneration !== recoveredLodSelection.surfaceReadback?.resourceGeneration,
|
|
387
|
+
)
|
|
388
|
+
) {
|
|
389
|
+
throw new Error('GPU-driven recovered Surface indirect parameters lost readback identity');
|
|
390
|
+
}
|
|
391
|
+
if (
|
|
392
|
+
recoveredLodSelection.submit === undefined ||
|
|
393
|
+
recoveredLodSelection.submit.frameId !== 2 ||
|
|
316
394
|
recoveredLodSelection.submit.deviceGeneration !== 0
|
|
317
395
|
) {
|
|
318
396
|
throw new Error('GPU-driven LOD telemetry reused a stale submit identity');
|
|
319
397
|
}
|
|
398
|
+
if (
|
|
399
|
+
lodSelection.surfaceReadback === undefined ||
|
|
400
|
+
recoveredLodSelection.surfaceReadback === undefined
|
|
401
|
+
) {
|
|
402
|
+
throw new Error('GPU-driven LOD telemetry lost Surface readback identity');
|
|
403
|
+
}
|
|
320
404
|
const validationError = await rawDevice.popErrorScope();
|
|
321
405
|
if (validationError !== null) {
|
|
322
406
|
throw new Error(`GPU-driven telemetry overlap validation failed: ${validationError.message}`);
|
|
@@ -348,6 +432,10 @@ export async function runGpuDrivenViewGpuEvidence(): Promise<GpuDrivenViewGpuEvi
|
|
|
348
432
|
firstInstance: indirectValue.getUint32(16, true),
|
|
349
433
|
overflow: overflowValue,
|
|
350
434
|
persistentTranslationX,
|
|
435
|
+
firstReadbackFrame: lodSelection.surfaceReadback.frameId,
|
|
436
|
+
recoveredReadbackFrame: recoveredLodSelection.surfaceReadback.frameId,
|
|
437
|
+
firstVisible: lodSelection.visible,
|
|
438
|
+
recoveredVisible: recoveredLodSelection.visible,
|
|
351
439
|
};
|
|
352
440
|
view.dispose();
|
|
353
441
|
sceneAvailability.scene.dispose();
|
|
@@ -12,7 +12,7 @@ import { RhiErrorListenerRegistry } from '../lifecycle';
|
|
|
12
12
|
import type { RenderFrameState } from '../record/frame-snapshot';
|
|
13
13
|
import { makeZeroCameraFallbackSnapshot } from '../record/frame-snapshot';
|
|
14
14
|
import type { PipelineState, RenderSystemInternals } from '../record/render-context';
|
|
15
|
-
import { ensureCompiledFrameGraph } from '../record/typed-frame-graph';
|
|
15
|
+
import { ensureCompiledFrameGraph, executeCompiledFrameGraph } from '../record/typed-frame-graph';
|
|
16
16
|
import type { RenderPipeline, RenderPipelineFrame } from '../render-pipeline';
|
|
17
17
|
import type {
|
|
18
18
|
ExtractedLights,
|
|
@@ -65,6 +65,7 @@ function updateSnapshot(value: RenderableSnapshot) {
|
|
|
65
65
|
function preparedFrame(view: GpuDrivenView): PreparedGpuDrivenFrame {
|
|
66
66
|
return {
|
|
67
67
|
topologySignature: `view-generation:${view.inspect().resourceGeneration}`,
|
|
68
|
+
worldKeys: [],
|
|
68
69
|
ownsAllDrawItems: true,
|
|
69
70
|
standardPbrFrameResources: {
|
|
70
71
|
materialBindGroups: [],
|
|
@@ -141,6 +142,7 @@ describe('GpuDrivenView graph projection', () => {
|
|
|
141
142
|
if (first === null) return;
|
|
142
143
|
const prepared: PreparedGpuDrivenFrame = {
|
|
143
144
|
topologySignature: 'stable-gpu-driven-test',
|
|
145
|
+
worldKeys: [],
|
|
144
146
|
ownsAllDrawItems: true,
|
|
145
147
|
standardPbrFrameResources: {
|
|
146
148
|
materialBindGroups: [],
|
|
@@ -239,7 +241,7 @@ describe('GpuDrivenView graph projection', () => {
|
|
|
239
241
|
{
|
|
240
242
|
name: 'gpu-driven.lod-selection-readback',
|
|
241
243
|
kind: 'copy',
|
|
242
|
-
dependencies: ['gpu-driven.frustum-compact'],
|
|
244
|
+
dependencies: ['gpu-driven.frustum-compact', 'gpu-driven.finalize-indirect'],
|
|
243
245
|
},
|
|
244
246
|
]);
|
|
245
247
|
const encoder = device.createCommandEncoder({ label: 'gpu-driven-view' }).unwrap();
|
|
@@ -390,7 +392,21 @@ describe('GpuDrivenView graph projection', () => {
|
|
|
390
392
|
const retirePrevious = vi.spyOn(compiledPrevious, 'retire');
|
|
391
393
|
const acceptedGraph = compile(preparedFrame(view), 2);
|
|
392
394
|
expect(acceptedGraph).not.toBe(compiledPrevious);
|
|
395
|
+
expect(retirePrevious).not.toHaveBeenCalled();
|
|
396
|
+
expect(destroyBuffer.mock.calls.some(([buffer]) => buffer === previousVisible)).toBe(false);
|
|
393
397
|
expect(frameState.compiledFrameGraphGeneration).toBe(2);
|
|
398
|
+
expect(retirePrevious).not.toHaveBeenCalled();
|
|
399
|
+
const acceptedEncoder = device
|
|
400
|
+
.createCommandEncoder({ label: 'gpu-driven-view-accepted' })
|
|
401
|
+
.unwrap();
|
|
402
|
+
expect(
|
|
403
|
+
executeCompiledFrameGraph(
|
|
404
|
+
internals,
|
|
405
|
+
frameState,
|
|
406
|
+
{ encoder: acceptedEncoder } as RenderPipelineFrame,
|
|
407
|
+
acceptedEncoder,
|
|
408
|
+
),
|
|
409
|
+
).toBe(true);
|
|
394
410
|
expect(retirePrevious).toHaveBeenCalledOnce();
|
|
395
411
|
await device.queue.onSubmittedWorkDone();
|
|
396
412
|
await Promise.resolve();
|
|
@@ -5,14 +5,7 @@ import {
|
|
|
5
5
|
} from './gpu-driven-view-gpu-evidence';
|
|
6
6
|
|
|
7
7
|
const browserReady = typeof navigator !== 'undefined' && navigator.gpu !== undefined;
|
|
8
|
-
const lifecycleFrames =
|
|
9
|
-
(
|
|
10
|
-
import.meta as ImportMeta & {
|
|
11
|
-
readonly env?: { readonly FORGEAX_BROWSER_CI_LIGHTWEIGHT?: string };
|
|
12
|
-
}
|
|
13
|
-
).env?.FORGEAX_BROWSER_CI_LIGHTWEIGHT === '1'
|
|
14
|
-
? 60
|
|
15
|
-
: 300;
|
|
8
|
+
const lifecycleFrames = 60;
|
|
16
9
|
|
|
17
10
|
describe.skipIf(!browserReady)('GPU-driven View Browser WebGPU', () => {
|
|
18
11
|
it('produces compact visible IDs and portable indirect args on the real browser device', async () => {
|
|
@@ -25,6 +18,10 @@ describe.skipIf(!browserReady)('GPU-driven View Browser WebGPU', () => {
|
|
|
25
18
|
firstInstance: 0,
|
|
26
19
|
overflow: 0,
|
|
27
20
|
persistentTranslationX: 0,
|
|
21
|
+
firstReadbackFrame: 10,
|
|
22
|
+
recoveredReadbackFrame: 11,
|
|
23
|
+
firstVisible: 1,
|
|
24
|
+
recoveredVisible: 0,
|
|
28
25
|
});
|
|
29
26
|
});
|
|
30
27
|
|
|
@@ -15,12 +15,16 @@ describe('GPU-driven View Dawn', () => {
|
|
|
15
15
|
firstInstance: 0,
|
|
16
16
|
overflow: 0,
|
|
17
17
|
persistentTranslationX: 0,
|
|
18
|
+
firstReadbackFrame: 10,
|
|
19
|
+
recoveredReadbackFrame: 11,
|
|
20
|
+
firstVisible: 1,
|
|
21
|
+
recoveredVisible: 0,
|
|
18
22
|
});
|
|
19
23
|
});
|
|
20
24
|
|
|
21
|
-
it('survives
|
|
25
|
+
it('survives 60 frames of spawn/despawn capacity crossings without stale buffers', async () => {
|
|
22
26
|
await expect(runGpuDrivenViewLifecycleEvidence()).resolves.toEqual({
|
|
23
|
-
frames:
|
|
27
|
+
frames: 60,
|
|
24
28
|
bufferRebuilds: 4,
|
|
25
29
|
candidateCapacity: 8,
|
|
26
30
|
});
|
|
@@ -99,7 +99,7 @@ describe('GPU-driven batch topology and CPU oracle', () => {
|
|
|
99
99
|
|
|
100
100
|
it('projects compact visible items into batch-local mesh and material indices', () => {
|
|
101
101
|
expect(GPU_DRIVEN_VIEW_WGSL).toMatch(
|
|
102
|
-
/
|
|
102
|
+
/vec4<u32>\(\s*candidate\.submitAdmission >> 1u,\s*materialOrPalette,\s*candidate\.primitiveIndex \+ 1u,\s*candidate\.generation,/,
|
|
103
103
|
);
|
|
104
104
|
expect(GPU_DRIVEN_VIEW_WGSL).toContain('(candidate.submitAdmission & 1u)');
|
|
105
105
|
expect(GPU_DRIVEN_VIEW_WGSL).toContain('instance.customDataStart');
|
|
@@ -145,6 +145,7 @@ describe('GPU pass timing generation-safe lifecycle', () => {
|
|
|
145
145
|
const oldReceipt = {
|
|
146
146
|
frameId: oldIdentity.frameId,
|
|
147
147
|
deviceGeneration: oldIdentity.deviceGeneration,
|
|
148
|
+
presentation: 'ready',
|
|
148
149
|
completed: Promise.resolve(ok(undefined)),
|
|
149
150
|
} as FrameReceipt;
|
|
150
151
|
store.register(oldReceipt, async () => {
|
|
@@ -17,9 +17,9 @@ describe.skipIf(!browserReady)('GPU pass timing Browser dev-server runner', () =
|
|
|
17
17
|
expect(omitted.timings).toBeUndefined();
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
20
|
+
// Each timing case creates a fresh renderer. Its lavapipe initialization can
|
|
21
|
+
// exceed Vitest's 15s default, including the raster-suppressed case below.
|
|
22
|
+
// Both retain the same bounded startup allowance and three-frame assertions.
|
|
23
23
|
it('keeps receipt facts and unsupported timing structured without stopping draw', {
|
|
24
24
|
timeout: 30_000,
|
|
25
25
|
}, async () => {
|
|
@@ -35,7 +35,9 @@ describe.skipIf(!browserReady)('GPU pass timing Browser dev-server runner', () =
|
|
|
35
35
|
expect(result.visible).toBe(true);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
it('keeps raster suppression as a test-only falsifier, never timing evidence',
|
|
38
|
+
it('keeps raster suppression as a test-only falsifier, never timing evidence', {
|
|
39
|
+
timeout: 30_000,
|
|
40
|
+
}, async () => {
|
|
39
41
|
const result = await runBrowserGpuPassTiming({ suppressRaster: true });
|
|
40
42
|
expect(result.rasterSuppressed).toBe(true);
|
|
41
43
|
expect(result.frames).toBe(3);
|
|
@@ -191,6 +191,123 @@ function createDevice(queue: RecordingQueue): RhiNullDevice {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
describe('GpuScene', () => {
|
|
194
|
+
it('keeps renderer-owned tables resident across World detach and reattach', () => {
|
|
195
|
+
const queue = new RecordingQueue();
|
|
196
|
+
const device = createDevice(queue);
|
|
197
|
+
const persistent = new PersistentRenderScene({ getDevice: () => device });
|
|
198
|
+
const firstWorld = new World();
|
|
199
|
+
const firstLease = createRenderReadLease(firstWorld);
|
|
200
|
+
|
|
201
|
+
persistent.extractComposition(
|
|
202
|
+
[firstWorld],
|
|
203
|
+
{ cameraOwner: 0, resourceOwner: 0 },
|
|
204
|
+
0,
|
|
205
|
+
() => persistentFrame([snapshot(1)]),
|
|
206
|
+
[firstLease],
|
|
207
|
+
);
|
|
208
|
+
const first = persistent.compositionGpuDrivenState();
|
|
209
|
+
expect(first).toBeDefined();
|
|
210
|
+
if (first === undefined) return;
|
|
211
|
+
|
|
212
|
+
persistent.detach(firstWorld);
|
|
213
|
+
firstLease.dispose();
|
|
214
|
+
const secondWorld = new World();
|
|
215
|
+
const secondLease = createRenderReadLease(secondWorld);
|
|
216
|
+
persistent.extractComposition(
|
|
217
|
+
[secondWorld],
|
|
218
|
+
{ cameraOwner: 0, resourceOwner: 0 },
|
|
219
|
+
1,
|
|
220
|
+
() => persistentFrame([snapshot(2)]),
|
|
221
|
+
[secondLease],
|
|
222
|
+
);
|
|
223
|
+
const second = persistent.compositionGpuDrivenState();
|
|
224
|
+
expect(second).toBeDefined();
|
|
225
|
+
expect(second?.scene).toBe(first.scene);
|
|
226
|
+
|
|
227
|
+
secondLease.dispose();
|
|
228
|
+
persistent.dispose();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('uploads only changed material bytes for shared value updates and retries failed writes', () => {
|
|
232
|
+
const queue = new FailingQueue();
|
|
233
|
+
const created = GpuScene.create(createDevice(queue), 8).unwrap();
|
|
234
|
+
expect(created.status).toBe('available');
|
|
235
|
+
if (created.status !== 'available') return;
|
|
236
|
+
const scene = created.scene;
|
|
237
|
+
const projection = new RenderScene();
|
|
238
|
+
const sources = Array.from({ length: 4 }, (_, index) => ({
|
|
239
|
+
...snapshot(index),
|
|
240
|
+
gpuDrivenDraws: [
|
|
241
|
+
{
|
|
242
|
+
kind: 'indexed' as const,
|
|
243
|
+
first: 0,
|
|
244
|
+
count: 36,
|
|
245
|
+
baseVertex: 0,
|
|
246
|
+
materialSlot: 0,
|
|
247
|
+
topology: 'triangle-list' as const,
|
|
248
|
+
pipelineClass: 'pbr',
|
|
249
|
+
materialResourceClass: '{}',
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
}));
|
|
253
|
+
scene.sync(projection.apply(sources.map(updateSnapshot))).unwrap();
|
|
254
|
+
const changed = { ...material, roughness: 0.3 };
|
|
255
|
+
const updated = sources.map((source) => ({
|
|
256
|
+
...source,
|
|
257
|
+
material: changed,
|
|
258
|
+
materials: [changed],
|
|
259
|
+
}));
|
|
260
|
+
const delta = projection.apply(updated.map(updateSnapshot));
|
|
261
|
+
queue.failWrites = true;
|
|
262
|
+
expect(scene.sync(delta).ok).toBe(false);
|
|
263
|
+
queue.failWrites = false;
|
|
264
|
+
queue.writes.length = 0;
|
|
265
|
+
const retried = scene.sync(projection.apply([])).unwrap();
|
|
266
|
+
expect(retried.bytes).toBe(4 * GPU_SCENE_LAYOUTS.material.stride);
|
|
267
|
+
expect(queue.writes).toHaveLength(1);
|
|
268
|
+
const roughness = gpuSceneFieldOffset(GPU_SCENE_LAYOUTS.material, 'roughness');
|
|
269
|
+
const upload = queue.writes[0];
|
|
270
|
+
if (upload === undefined) throw new Error('expected material upload');
|
|
271
|
+
for (let index = 0; index < 4; index++) {
|
|
272
|
+
expect(
|
|
273
|
+
new DataView(upload.bytes.buffer).getFloat32(
|
|
274
|
+
index * GPU_SCENE_LAYOUTS.material.stride + roughness,
|
|
275
|
+
true,
|
|
276
|
+
),
|
|
277
|
+
).toBeCloseTo(0.3);
|
|
278
|
+
}
|
|
279
|
+
// Fresh snapshots with identical bytes must not upload. Later in-place
|
|
280
|
+
// caller edits remain visible: packed rows are shared only within sync.
|
|
281
|
+
expect(scene.sync(projection.apply(updated.map(updateSnapshot))).unwrap().bytes).toBe(0);
|
|
282
|
+
changed.roughness = 0.6;
|
|
283
|
+
expect(scene.sync(projection.apply(updated.map(updateSnapshot))).unwrap().bytes).toBe(
|
|
284
|
+
4 * GPU_SCENE_LAYOUTS.material.stride,
|
|
285
|
+
);
|
|
286
|
+
const first = updated[0];
|
|
287
|
+
const draw = first?.gpuDrivenDraws[0];
|
|
288
|
+
if (first === undefined || draw === undefined) throw new Error('expected draw fixture');
|
|
289
|
+
queue.writes.length = 0;
|
|
290
|
+
const geometryChanged = {
|
|
291
|
+
...first,
|
|
292
|
+
localAabb: new Float32Array([-2, -1, -1, 2, 1, 1]),
|
|
293
|
+
gpuDrivenDraws: [{ ...draw, first: 6, count: 12, baseVertex: -3 }],
|
|
294
|
+
};
|
|
295
|
+
expect(scene.sync(projection.apply([updateSnapshot(geometryChanged)])).unwrap().bytes).toBe(
|
|
296
|
+
GPU_SCENE_LAYOUTS.primitive.stride + GPU_SCENE_LAYOUTS.drawTemplate.stride,
|
|
297
|
+
);
|
|
298
|
+
const drawUpload = queue.writes.find(
|
|
299
|
+
({ bytes }) => bytes.length === GPU_SCENE_LAYOUTS.drawTemplate.stride,
|
|
300
|
+
);
|
|
301
|
+
if (drawUpload === undefined) throw new Error('expected changed draw upload');
|
|
302
|
+
expect(
|
|
303
|
+
new DataView(drawUpload.bytes.buffer).getInt32(
|
|
304
|
+
gpuSceneFieldOffset(GPU_SCENE_LAYOUTS.drawTemplate, 'baseVertex'),
|
|
305
|
+
true,
|
|
306
|
+
),
|
|
307
|
+
).toBe(-3);
|
|
308
|
+
scene.dispose();
|
|
309
|
+
});
|
|
310
|
+
|
|
194
311
|
it('preserves authored base-color alpha in the scene material row', () => {
|
|
195
312
|
const row = packStandardPbrMaterialRow(createStandardPbrArtifactReceipt(), {
|
|
196
313
|
...material,
|
|
@@ -888,20 +1005,13 @@ describe('GpuScene', () => {
|
|
|
888
1005
|
expect(delta.updated).toBe(1);
|
|
889
1006
|
const result = created.scene.sync(delta).unwrap();
|
|
890
1007
|
expect(result.bytes).toBe(
|
|
891
|
-
GPU_SCENE_LAYOUTS.
|
|
892
|
-
GPU_SCENE_LAYOUTS.drawTemplate.stride +
|
|
893
|
-
GPU_SCENE_LAYOUTS.material.stride +
|
|
894
|
-
2 * GPU_SCENE_LAYOUTS.transform.stride,
|
|
1008
|
+
GPU_SCENE_LAYOUTS.material.stride + 2 * GPU_SCENE_LAYOUTS.transform.stride,
|
|
895
1009
|
);
|
|
896
1010
|
expect(result.grew).toBe(false);
|
|
897
1011
|
const next = { ...mixed, material: { ...nextMaterial, roughness: 0.7 } };
|
|
898
1012
|
next.materials = [next.material];
|
|
899
1013
|
const materialOnly = created.scene.sync(projection.apply([updateSnapshot(next)])).unwrap();
|
|
900
|
-
expect(materialOnly.bytes).toBe(
|
|
901
|
-
GPU_SCENE_LAYOUTS.primitive.stride +
|
|
902
|
-
GPU_SCENE_LAYOUTS.drawTemplate.stride +
|
|
903
|
-
GPU_SCENE_LAYOUTS.material.stride,
|
|
904
|
-
);
|
|
1014
|
+
expect(materialOnly.bytes).toBe(GPU_SCENE_LAYOUTS.material.stride);
|
|
905
1015
|
});
|
|
906
1016
|
});
|
|
907
1017
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { err, RhiError } from '@forgeax/engine-rhi';
|
|
2
|
+
import { rhi } from '@forgeax/engine-rhi-null';
|
|
3
|
+
import { expect, it, vi } from 'vitest';
|
|
4
|
+
import { GPU_SHADER_STAGE_VERTEX } from '../gpu-stage';
|
|
5
|
+
import { GPU_BUFFER_USAGE_STORAGE } from '../gpu-usage';
|
|
6
|
+
import { resolveGeometryInstanceBuffer } from '../record/main-pass-geometry';
|
|
7
|
+
|
|
8
|
+
it('refuses an instance draw when allocation fails instead of drawing the identity fallback', async () => {
|
|
9
|
+
const device = (await (await rhi.requestAdapter()).unwrap().requestDevice()).unwrap();
|
|
10
|
+
const identity = device.createBuffer({ size: 128, usage: GPU_BUFFER_USAGE_STORAGE }).unwrap();
|
|
11
|
+
const layout = device
|
|
12
|
+
.createBindGroupLayout({
|
|
13
|
+
entries: [
|
|
14
|
+
{ binding: 0, visibility: GPU_SHADER_STAGE_VERTEX, buffer: { type: 'read-only-storage' } },
|
|
15
|
+
],
|
|
16
|
+
})
|
|
17
|
+
.unwrap();
|
|
18
|
+
const failure = new RhiError({
|
|
19
|
+
code: 'rhi-not-available',
|
|
20
|
+
expected: 'an instance buffer allocation',
|
|
21
|
+
hint: 'recover the renderer',
|
|
22
|
+
});
|
|
23
|
+
const allocation = vi.spyOn(device, 'createBuffer').mockReturnValue(err(failure));
|
|
24
|
+
const bindGroup = vi.spyOn(device, 'createBindGroup');
|
|
25
|
+
const fire = vi.fn();
|
|
26
|
+
try {
|
|
27
|
+
const result = resolveGeometryInstanceBuffer(
|
|
28
|
+
{
|
|
29
|
+
runtime: { device, errorRegistry: { fire } },
|
|
30
|
+
pipelineState: { identityInstanceBuffer: identity, instancesBindGroupLayout: layout },
|
|
31
|
+
frameState: { instanceBuffers: new Map() },
|
|
32
|
+
bindGroupCounts: { createBindGroup: 0, keys: [] },
|
|
33
|
+
} as unknown as Parameters<typeof resolveGeometryInstanceBuffer>[0],
|
|
34
|
+
{
|
|
35
|
+
source: {
|
|
36
|
+
worldId: 0,
|
|
37
|
+
entityKey: 1,
|
|
38
|
+
instances: {
|
|
39
|
+
transforms: new Float32Array(32),
|
|
40
|
+
instanceCount: 2,
|
|
41
|
+
cacheKey: 1,
|
|
42
|
+
archVersion: 0,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
} as Parameters<typeof resolveGeometryInstanceBuffer>[1],
|
|
46
|
+
[],
|
|
47
|
+
false,
|
|
48
|
+
);
|
|
49
|
+
expect(result).toBeNull();
|
|
50
|
+
expect(fire).toHaveBeenCalledWith(failure);
|
|
51
|
+
expect(bindGroup).not.toHaveBeenCalled();
|
|
52
|
+
} finally {
|
|
53
|
+
allocation.mockRestore();
|
|
54
|
+
bindGroup.mockRestore();
|
|
55
|
+
device.destroyBuffer(identity).unwrap();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
@@ -7,8 +7,6 @@ import { Instances } from '../components/instances';
|
|
|
7
7
|
import { MeshFilter } from '../components/mesh-filter';
|
|
8
8
|
import { MeshRenderer } from '../components/mesh-renderer';
|
|
9
9
|
import { GPU_DRIVEN_VIEW_WGSL } from '../gpu-driven/view-gpu';
|
|
10
|
-
import type { InstanceCollectionId } from '../instances';
|
|
11
|
-
import { InstanceCollectionStore } from '../instances';
|
|
12
10
|
import { extractFrames } from '../render-system-extract';
|
|
13
11
|
|
|
14
12
|
const IDENTITY = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
|
|
@@ -28,21 +26,13 @@ function spawnCamera(world: World): void {
|
|
|
28
26
|
.unwrap();
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
function spawnInstancedCube(
|
|
32
|
-
world: World,
|
|
33
|
-
instanceCollections: InstanceCollectionStore,
|
|
34
|
-
entityX: number,
|
|
35
|
-
instanceX: number,
|
|
36
|
-
) {
|
|
37
|
-
const collectionId = instanceCollections
|
|
38
|
-
.create({ transforms: translated(instanceX) })
|
|
39
|
-
.unwrap().collectionId;
|
|
29
|
+
function spawnInstancedCube(world: World, entityX: number, instanceX: number) {
|
|
40
30
|
return world
|
|
41
31
|
.spawn(
|
|
42
32
|
{ component: Transform, data: { pos: [entityX, 0, 0] } },
|
|
43
33
|
{ component: MeshFilter, data: { assetHandle: HANDLE_CUBE } },
|
|
44
34
|
{ component: MeshRenderer, data: {} },
|
|
45
|
-
{ component: Instances, data: {
|
|
35
|
+
{ component: Instances, data: { transforms: translated(instanceX) } },
|
|
46
36
|
)
|
|
47
37
|
.unwrap();
|
|
48
38
|
}
|
|
@@ -52,13 +42,10 @@ describe('Instances CPU/GPU culling ownership', () => {
|
|
|
52
42
|
const world = new World();
|
|
53
43
|
registerPropagateTransforms(world);
|
|
54
44
|
spawnCamera(world);
|
|
55
|
-
const
|
|
56
|
-
const entity = spawnInstancedCube(world, instanceCollections, 20, -20);
|
|
45
|
+
const entity = spawnInstancedCube(world, 20, -20);
|
|
57
46
|
world.update(0).unwrap();
|
|
58
47
|
|
|
59
|
-
const frame = extractFrames([world], 0
|
|
60
|
-
instanceCollections,
|
|
61
|
-
});
|
|
48
|
+
const frame = extractFrames([world], 0);
|
|
62
49
|
|
|
63
50
|
expect(frame.renderables.map((renderable) => renderable.entityKey)).toContain(entity);
|
|
64
51
|
expect(frame.frustumStats).toEqual({ culled: 0, total: 1 });
|
|
@@ -68,22 +55,15 @@ describe('Instances CPU/GPU culling ownership', () => {
|
|
|
68
55
|
const world = new World();
|
|
69
56
|
registerPropagateTransforms(world);
|
|
70
57
|
spawnCamera(world);
|
|
71
|
-
const
|
|
72
|
-
const entity = spawnInstancedCube(world, instanceCollections, 20, -20);
|
|
58
|
+
const entity = spawnInstancedCube(world, 20, -20);
|
|
73
59
|
world.update(0).unwrap();
|
|
74
|
-
expect(
|
|
75
|
-
extractFrames([world], 0, undefined, undefined, undefined, { instanceCollections })
|
|
76
|
-
.renderables,
|
|
77
|
-
).toHaveLength(1);
|
|
60
|
+
expect(extractFrames([world], 0).renderables).toHaveLength(1);
|
|
78
61
|
|
|
79
62
|
world.set(entity, Transform, { pos: [40, 0, 0] }).unwrap();
|
|
80
|
-
|
|
81
|
-
instanceCollections.replace(collectionId as InstanceCollectionId, translated(-40)).unwrap();
|
|
63
|
+
world.set(entity, Instances, { transforms: translated(-40) }).unwrap();
|
|
82
64
|
world.update(0).unwrap();
|
|
83
65
|
|
|
84
|
-
const frame = extractFrames([world], 0
|
|
85
|
-
instanceCollections,
|
|
86
|
-
});
|
|
66
|
+
const frame = extractFrames([world], 0);
|
|
87
67
|
expect(frame.renderables).toHaveLength(1);
|
|
88
68
|
expect(frame.renderables[0]?.instances?.instanceCount).toBe(1);
|
|
89
69
|
});
|
|
@@ -92,23 +72,17 @@ describe('Instances CPU/GPU culling ownership', () => {
|
|
|
92
72
|
const world = new World();
|
|
93
73
|
registerPropagateTransforms(world);
|
|
94
74
|
spawnCamera(world);
|
|
95
|
-
const instanceCollections = new InstanceCollectionStore();
|
|
96
|
-
const collectionId = instanceCollections
|
|
97
|
-
.create({ transforms: new Float32Array() })
|
|
98
|
-
.unwrap().collectionId;
|
|
99
75
|
const entity = world
|
|
100
76
|
.spawn(
|
|
101
77
|
{ component: Transform, data: { pos: [20, 0, 0] } },
|
|
102
78
|
{ component: MeshFilter, data: { assetHandle: HANDLE_CUBE } },
|
|
103
79
|
{ component: MeshRenderer, data: {} },
|
|
104
|
-
{ component: Instances, data: {
|
|
80
|
+
{ component: Instances, data: { transforms: new Float32Array() } },
|
|
105
81
|
)
|
|
106
82
|
.unwrap();
|
|
107
83
|
world.update(0).unwrap();
|
|
108
84
|
|
|
109
|
-
const frame = extractFrames([world], 0
|
|
110
|
-
instanceCollections,
|
|
111
|
-
});
|
|
85
|
+
const frame = extractFrames([world], 0);
|
|
112
86
|
expect(
|
|
113
87
|
frame.renderables.find((renderable) => renderable.entityKey === entity)?.instances,
|
|
114
88
|
).toMatchObject({ instanceCount: 0 });
|