@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,147 @@
|
|
|
1
|
+
import type { RhiCaps } from '@forgeax/engine-rhi';
|
|
2
|
+
import type { MaterialProgramAbi, MaterialSurfacePassKind } from '@forgeax/engine-types';
|
|
3
|
+
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
4
|
+
|
|
5
|
+
export type SurfaceGpuCapability = 'compute' | 'storageBuffer' | 'indirectDrawing';
|
|
6
|
+
export type SurfaceGpuFallbackReason = SurfaceGpuCapability;
|
|
7
|
+
|
|
8
|
+
export type SurfaceGpuSubmissionErrorCode =
|
|
9
|
+
| 'surface-abi-missing'
|
|
10
|
+
| 'surface-pass-missing'
|
|
11
|
+
| 'surface-producer-not-ready'
|
|
12
|
+
| 'surface-generation-stale';
|
|
13
|
+
|
|
14
|
+
export interface SurfaceGpuSubmissionError {
|
|
15
|
+
readonly code: SurfaceGpuSubmissionErrorCode;
|
|
16
|
+
readonly expected: string;
|
|
17
|
+
readonly hint: string;
|
|
18
|
+
readonly pass: MaterialSurfacePassKind;
|
|
19
|
+
readonly owner: 'surface-producer' | 'render-scene' | 'render-generation';
|
|
20
|
+
readonly actual?: unknown;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface SurfaceGpuPassAdmission {
|
|
24
|
+
readonly pass: MaterialSurfacePassKind;
|
|
25
|
+
readonly lane: 'gpu-driven' | 'direct';
|
|
26
|
+
readonly reason?: SurfaceGpuFallbackReason;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface SurfaceGpuSubmissionAdmission {
|
|
30
|
+
readonly model: 'single-layer-medium';
|
|
31
|
+
readonly lane: 'gpu-driven' | 'direct';
|
|
32
|
+
readonly passes: readonly [SurfaceGpuPassAdmission, SurfaceGpuPassAdmission];
|
|
33
|
+
readonly deviceGeneration: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface SurfaceGpuSubmissionInput {
|
|
37
|
+
readonly abi: MaterialProgramAbi;
|
|
38
|
+
readonly caps: Pick<RhiCaps, 'compute' | 'storageBuffer' | 'indirectDrawing'>;
|
|
39
|
+
readonly sceneIndexReady: boolean;
|
|
40
|
+
readonly resourcesReady: boolean;
|
|
41
|
+
readonly dynamicInputReady: boolean;
|
|
42
|
+
readonly deviceGeneration: number;
|
|
43
|
+
readonly preparedDeviceGeneration: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const ERROR_POLICY: Readonly<
|
|
47
|
+
Record<SurfaceGpuSubmissionErrorCode, { readonly expected: string; readonly hint: string }>
|
|
48
|
+
> = {
|
|
49
|
+
'surface-abi-missing': {
|
|
50
|
+
expected: 'a producer-published single-layer-medium ABI is present',
|
|
51
|
+
hint: 'compose, reflect, and publish the Surface model before preparing the draw',
|
|
52
|
+
},
|
|
53
|
+
'surface-pass-missing': {
|
|
54
|
+
expected: 'the published model contains both nearest-layer and color passes',
|
|
55
|
+
hint: 'recook the complete model publication; do not synthesize a missing pass',
|
|
56
|
+
},
|
|
57
|
+
'surface-producer-not-ready': {
|
|
58
|
+
expected: 'scene-index, resources, and dynamic input facts are ready for the published model',
|
|
59
|
+
hint: 'repair the owning producer publication and retry; capability fallback does not cover stale assets',
|
|
60
|
+
},
|
|
61
|
+
'surface-generation-stale': {
|
|
62
|
+
expected: 'prepared Surface facts belong to the current device generation',
|
|
63
|
+
hint: 'rebuild the prepared surface resources for the current device generation',
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function failure(
|
|
68
|
+
code: SurfaceGpuSubmissionErrorCode,
|
|
69
|
+
pass: MaterialSurfacePassKind,
|
|
70
|
+
owner: SurfaceGpuSubmissionError['owner'],
|
|
71
|
+
actual?: unknown,
|
|
72
|
+
): SurfaceGpuSubmissionError {
|
|
73
|
+
return {
|
|
74
|
+
code,
|
|
75
|
+
expected: ERROR_POLICY[code].expected,
|
|
76
|
+
hint: ERROR_POLICY[code].hint,
|
|
77
|
+
pass,
|
|
78
|
+
owner,
|
|
79
|
+
...(actual === undefined ? {} : { actual }),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function capabilityFallback(
|
|
84
|
+
caps: SurfaceGpuSubmissionInput['caps'],
|
|
85
|
+
): SurfaceGpuFallbackReason | undefined {
|
|
86
|
+
if (!caps.compute) return 'compute';
|
|
87
|
+
if (!caps.storageBuffer) return 'storageBuffer';
|
|
88
|
+
if (!caps.indirectDrawing) return 'indirectDrawing';
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Admit the two Surface passes together. Capability fallback is explicit and
|
|
94
|
+
* symmetric; a missing promised publication is a producer error and never a
|
|
95
|
+
* silent direct fallback.
|
|
96
|
+
*/
|
|
97
|
+
export function admitSingleLayerMediumSubmission(
|
|
98
|
+
input: SurfaceGpuSubmissionInput,
|
|
99
|
+
): Result<SurfaceGpuSubmissionAdmission, SurfaceGpuSubmissionError> {
|
|
100
|
+
const firstPass: MaterialSurfacePassKind = 'nearest-layer';
|
|
101
|
+
const surface = input.abi.surface;
|
|
102
|
+
if (surface === undefined || surface.model !== 'single-layer-medium') {
|
|
103
|
+
return err(failure('surface-abi-missing', firstPass, 'surface-producer', surface));
|
|
104
|
+
}
|
|
105
|
+
if (!surface.passes.includes('nearest-layer') || !surface.passes.includes('color')) {
|
|
106
|
+
return err(failure('surface-pass-missing', firstPass, 'surface-producer', surface.passes));
|
|
107
|
+
}
|
|
108
|
+
if (input.deviceGeneration !== input.preparedDeviceGeneration) {
|
|
109
|
+
return err(
|
|
110
|
+
failure('surface-generation-stale', firstPass, 'render-generation', {
|
|
111
|
+
deviceGeneration: input.deviceGeneration,
|
|
112
|
+
preparedDeviceGeneration: input.preparedDeviceGeneration,
|
|
113
|
+
}),
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const dynamicRequired = surface.dynamicInput !== undefined;
|
|
117
|
+
if (
|
|
118
|
+
!input.sceneIndexReady ||
|
|
119
|
+
!input.resourcesReady ||
|
|
120
|
+
(dynamicRequired && !input.dynamicInputReady)
|
|
121
|
+
) {
|
|
122
|
+
return err(
|
|
123
|
+
failure('surface-producer-not-ready', firstPass, 'surface-producer', {
|
|
124
|
+
sceneIndexReady: input.sceneIndexReady,
|
|
125
|
+
resourcesReady: input.resourcesReady,
|
|
126
|
+
dynamicInputReady: input.dynamicInputReady,
|
|
127
|
+
}),
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
const fallback = capabilityFallback(input.caps);
|
|
131
|
+
const admitted: [SurfaceGpuPassAdmission, SurfaceGpuPassAdmission] =
|
|
132
|
+
fallback === undefined
|
|
133
|
+
? [
|
|
134
|
+
{ pass: firstPass, lane: 'gpu-driven' },
|
|
135
|
+
{ pass: 'color', lane: 'gpu-driven' },
|
|
136
|
+
]
|
|
137
|
+
: [
|
|
138
|
+
{ pass: firstPass, lane: 'direct', reason: fallback },
|
|
139
|
+
{ pass: 'color', lane: 'direct', reason: fallback },
|
|
140
|
+
];
|
|
141
|
+
return ok({
|
|
142
|
+
model: 'single-layer-medium',
|
|
143
|
+
lane: fallback === undefined ? 'gpu-driven' : 'direct',
|
|
144
|
+
passes: admitted,
|
|
145
|
+
deviceGeneration: input.deviceGeneration,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
2
|
+
import type { GpuDrivenLaneReason, PersistentRenderSceneInspection } from '../inspection-types';
|
|
3
|
+
|
|
4
|
+
export type SurfacePassName = 'nearest-layer' | 'color';
|
|
5
|
+
|
|
6
|
+
type SurfaceDirectCommandObservation = {
|
|
7
|
+
readonly kind: 'draw' | 'draw-indexed';
|
|
8
|
+
readonly count: number;
|
|
9
|
+
readonly first: number;
|
|
10
|
+
readonly instanceCount: number;
|
|
11
|
+
readonly firstInstance: number;
|
|
12
|
+
readonly surfaceFrameBase: number;
|
|
13
|
+
readonly memberIds: readonly string[];
|
|
14
|
+
readonly pipelineIdentity: number;
|
|
15
|
+
readonly receiptIdentity?: string;
|
|
16
|
+
readonly receiptGeneration?: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type SurfaceIndirectCommandObservation = {
|
|
20
|
+
readonly kind: 'draw-indirect' | 'draw-indexed-indirect';
|
|
21
|
+
readonly indirectBufferIdentity: number;
|
|
22
|
+
readonly indirectOffset: number;
|
|
23
|
+
readonly pipelineIdentity: number;
|
|
24
|
+
readonly receiptIdentity?: string;
|
|
25
|
+
readonly receiptGeneration?: number;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** The five words written by the GPU indirect finalizer, with its owner fence. */
|
|
29
|
+
export interface SurfaceGpuIndirectParameters {
|
|
30
|
+
readonly sequence: number;
|
|
31
|
+
readonly frameId: number;
|
|
32
|
+
readonly deviceGeneration: number;
|
|
33
|
+
readonly resourceGeneration: number | undefined;
|
|
34
|
+
readonly viewIdentity: 'main:0';
|
|
35
|
+
readonly pass: SurfacePassName;
|
|
36
|
+
readonly kind: 'draw-indirect' | 'draw-indexed-indirect';
|
|
37
|
+
readonly indirectBufferIdentity: number;
|
|
38
|
+
readonly indirectOffset: number;
|
|
39
|
+
readonly count: number;
|
|
40
|
+
readonly first: number;
|
|
41
|
+
readonly instanceCount: number;
|
|
42
|
+
readonly baseVertex: number;
|
|
43
|
+
readonly firstInstance: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type SurfaceGpuIndirectReadbackErrorCode =
|
|
47
|
+
| 'indirect-readback-metadata-mismatch'
|
|
48
|
+
| 'indirect-readback-truncated';
|
|
49
|
+
|
|
50
|
+
export interface SurfaceGpuIndirectReadbackError {
|
|
51
|
+
readonly code: SurfaceGpuIndirectReadbackErrorCode;
|
|
52
|
+
readonly expected: string;
|
|
53
|
+
readonly hint: string;
|
|
54
|
+
readonly actual: unknown;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type SurfaceCommandObservation =
|
|
58
|
+
| SurfaceDirectCommandObservation
|
|
59
|
+
| SurfaceIndirectCommandObservation;
|
|
60
|
+
|
|
61
|
+
type StoredSurfaceCommandObservation = SurfaceCommandObservation & {
|
|
62
|
+
readonly programEvidence: 'producer-receipt' | 'missing';
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export interface SurfaceGpuReadbackPassSnapshot {
|
|
66
|
+
readonly pass: SurfacePassName;
|
|
67
|
+
readonly totalCommandCount: number;
|
|
68
|
+
readonly savedCommandCount: number;
|
|
69
|
+
readonly droppedCommandCount: number;
|
|
70
|
+
readonly truncated: boolean;
|
|
71
|
+
readonly ranges: readonly {
|
|
72
|
+
readonly kind: 'draw-indirect' | 'draw-indexed-indirect';
|
|
73
|
+
readonly indirectBufferIdentity: number;
|
|
74
|
+
readonly indirectOffset: number;
|
|
75
|
+
}[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Identity of the exact recording whose selector bytes entered the readback buffer. */
|
|
79
|
+
export interface SurfaceGpuReadbackSnapshot {
|
|
80
|
+
readonly sequence: number;
|
|
81
|
+
readonly frameId: number;
|
|
82
|
+
readonly deviceGeneration: number;
|
|
83
|
+
readonly resourceGeneration: number | undefined;
|
|
84
|
+
readonly viewIdentity: string;
|
|
85
|
+
readonly passes: readonly SurfaceGpuReadbackPassSnapshot[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface SurfaceGpuMemberReadback {
|
|
89
|
+
readonly recording: SurfaceGpuReadbackSnapshot;
|
|
90
|
+
readonly memberIds: readonly string[];
|
|
91
|
+
readonly indirectParameters?: readonly SurfaceGpuIndirectParameters[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Decode only ranges recorded by the Surface submission owner. */
|
|
95
|
+
export function decodeSurfaceIndirectParameters(input: {
|
|
96
|
+
readonly bytes: ArrayBuffer;
|
|
97
|
+
readonly byteOffset: number;
|
|
98
|
+
readonly byteLength: number;
|
|
99
|
+
readonly indirectBufferIdentity: number;
|
|
100
|
+
readonly recording: SurfaceGpuReadbackSnapshot;
|
|
101
|
+
}): Result<readonly SurfaceGpuIndirectParameters[], SurfaceGpuIndirectReadbackError> {
|
|
102
|
+
const ranges = input.recording.passes.flatMap((pass) =>
|
|
103
|
+
pass.ranges.map((range) => ({ pass: pass.pass, ...range })),
|
|
104
|
+
);
|
|
105
|
+
if (
|
|
106
|
+
input.byteOffset < 0 ||
|
|
107
|
+
input.byteLength < 0 ||
|
|
108
|
+
input.byteOffset + input.byteLength > input.bytes.byteLength
|
|
109
|
+
) {
|
|
110
|
+
return err({
|
|
111
|
+
code: 'indirect-readback-truncated',
|
|
112
|
+
expected: 'the indirect readback range is contained by the mapped buffer',
|
|
113
|
+
hint: 'retain the complete GPU indirect command copy before mapping it',
|
|
114
|
+
actual: {
|
|
115
|
+
byteOffset: input.byteOffset,
|
|
116
|
+
byteLength: input.byteLength,
|
|
117
|
+
bufferBytes: input.bytes.byteLength,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const values = new DataView(input.bytes, input.byteOffset, input.byteLength);
|
|
122
|
+
const decoded: SurfaceGpuIndirectParameters[] = [];
|
|
123
|
+
for (const range of ranges) {
|
|
124
|
+
if (range.indirectBufferIdentity !== input.indirectBufferIdentity) {
|
|
125
|
+
return err({
|
|
126
|
+
code: 'indirect-readback-metadata-mismatch',
|
|
127
|
+
expected: 'every Surface indirect range names the copied indirect buffer',
|
|
128
|
+
hint: 'discard the readback and wait for the matching resource generation',
|
|
129
|
+
actual: {
|
|
130
|
+
pass: range.pass,
|
|
131
|
+
expectedBufferIdentity: input.indirectBufferIdentity,
|
|
132
|
+
actualBufferIdentity: range.indirectBufferIdentity,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const offset = range.indirectOffset;
|
|
137
|
+
if (
|
|
138
|
+
!Number.isInteger(offset) ||
|
|
139
|
+
offset < 0 ||
|
|
140
|
+
offset % 4 !== 0 ||
|
|
141
|
+
offset + 20 > values.byteLength
|
|
142
|
+
) {
|
|
143
|
+
return err({
|
|
144
|
+
code: 'indirect-readback-truncated',
|
|
145
|
+
expected: 'each indirect range is a 20-byte aligned command inside the copied buffer',
|
|
146
|
+
hint: 'discard truncated selector readback instead of publishing partial draw parameters',
|
|
147
|
+
actual: { pass: range.pass, indirectOffset: offset, readbackBytes: values.byteLength },
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const indexed = range.kind === 'draw-indexed-indirect';
|
|
151
|
+
decoded.push(
|
|
152
|
+
Object.freeze({
|
|
153
|
+
sequence: input.recording.sequence,
|
|
154
|
+
frameId: input.recording.frameId,
|
|
155
|
+
deviceGeneration: input.recording.deviceGeneration,
|
|
156
|
+
resourceGeneration: input.recording.resourceGeneration,
|
|
157
|
+
viewIdentity: input.recording.viewIdentity as 'main:0',
|
|
158
|
+
pass: range.pass,
|
|
159
|
+
kind: range.kind,
|
|
160
|
+
indirectBufferIdentity: range.indirectBufferIdentity,
|
|
161
|
+
indirectOffset: offset,
|
|
162
|
+
count: values.getUint32(offset, true),
|
|
163
|
+
first: values.getUint32(offset + 8, true),
|
|
164
|
+
instanceCount: values.getUint32(offset + 4, true),
|
|
165
|
+
baseVertex: indexed ? values.getInt32(offset + 12, true) : 0,
|
|
166
|
+
firstInstance: values.getUint32(indexed ? offset + 16 : offset + 12, true),
|
|
167
|
+
}),
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return ok(Object.freeze(decoded));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
interface SurfacePassRecording {
|
|
174
|
+
readonly commands: StoredSurfaceCommandObservation[];
|
|
175
|
+
totalCommandCount: number;
|
|
176
|
+
sawIndirect: boolean;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
type SurfaceSubmission = NonNullable<PersistentRenderSceneInspection['submission']>;
|
|
180
|
+
|
|
181
|
+
const MAX_COMMANDS_PER_PASS = 32;
|
|
182
|
+
|
|
183
|
+
function isIndirect(
|
|
184
|
+
command: SurfaceCommandObservation,
|
|
185
|
+
): command is SurfaceIndirectCommandObservation {
|
|
186
|
+
return command.kind === 'draw-indirect' || command.kind === 'draw-indexed-indirect';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function sameReadbackPass(
|
|
190
|
+
receipt: SurfaceSubmission['passes'][number],
|
|
191
|
+
snapshot: SurfaceGpuReadbackPassSnapshot,
|
|
192
|
+
): boolean {
|
|
193
|
+
if (
|
|
194
|
+
receipt.pass !== snapshot.pass ||
|
|
195
|
+
receipt.totalCommandCount !== snapshot.totalCommandCount ||
|
|
196
|
+
receipt.savedCommandCount !== snapshot.savedCommandCount ||
|
|
197
|
+
receipt.droppedCommandCount !== snapshot.droppedCommandCount ||
|
|
198
|
+
receipt.truncated !== snapshot.truncated
|
|
199
|
+
) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
const ranges = receipt.commands.flatMap((command) =>
|
|
203
|
+
command.kind === 'draw-indirect' || command.kind === 'draw-indexed-indirect'
|
|
204
|
+
? [
|
|
205
|
+
{
|
|
206
|
+
kind: command.kind,
|
|
207
|
+
indirectBufferIdentity: command.indirectBufferIdentity,
|
|
208
|
+
indirectOffset: command.indirectOffset,
|
|
209
|
+
},
|
|
210
|
+
]
|
|
211
|
+
: [],
|
|
212
|
+
);
|
|
213
|
+
return (
|
|
214
|
+
ranges.length === snapshot.ranges.length &&
|
|
215
|
+
ranges.every((range, index) => {
|
|
216
|
+
const expected = snapshot.ranges[index];
|
|
217
|
+
return (
|
|
218
|
+
expected !== undefined &&
|
|
219
|
+
range.kind === expected.kind &&
|
|
220
|
+
range.indirectBufferIdentity === expected.indirectBufferIdentity &&
|
|
221
|
+
range.indirectOffset === expected.indirectOffset
|
|
222
|
+
);
|
|
223
|
+
})
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function sameIndirectParameters(
|
|
228
|
+
recording: SurfaceGpuReadbackSnapshot,
|
|
229
|
+
parameters: readonly SurfaceGpuIndirectParameters[],
|
|
230
|
+
): boolean {
|
|
231
|
+
const expected = recording.passes.flatMap((pass) =>
|
|
232
|
+
pass.ranges.map((range) => ({ pass: pass.pass, ...range })),
|
|
233
|
+
);
|
|
234
|
+
return (
|
|
235
|
+
expected.length === parameters.length &&
|
|
236
|
+
expected.every((range, index) => {
|
|
237
|
+
const actual = parameters[index];
|
|
238
|
+
return (
|
|
239
|
+
actual !== undefined &&
|
|
240
|
+
actual.sequence === recording.sequence &&
|
|
241
|
+
actual.frameId === recording.frameId &&
|
|
242
|
+
actual.deviceGeneration === recording.deviceGeneration &&
|
|
243
|
+
actual.resourceGeneration === recording.resourceGeneration &&
|
|
244
|
+
actual.viewIdentity === recording.viewIdentity &&
|
|
245
|
+
actual.pass === range.pass &&
|
|
246
|
+
actual.kind === range.kind &&
|
|
247
|
+
actual.indirectBufferIdentity === range.indirectBufferIdentity &&
|
|
248
|
+
actual.indirectOffset === range.indirectOffset
|
|
249
|
+
);
|
|
250
|
+
})
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export class SurfaceSubmissionCandidate {
|
|
255
|
+
private readonly passes = new Map<SurfacePassName, SurfacePassRecording>();
|
|
256
|
+
private state: 'recording' | 'submitted' | 'aborted' = 'recording';
|
|
257
|
+
private resolvedResourceGeneration: number | undefined;
|
|
258
|
+
private actualLaneReason: GpuDrivenLaneReason | undefined;
|
|
259
|
+
|
|
260
|
+
constructor(
|
|
261
|
+
private readonly owner: SurfaceSubmissionObservationOwner,
|
|
262
|
+
readonly sequence: number,
|
|
263
|
+
readonly frameId: number,
|
|
264
|
+
readonly requestedLane: 'direct' | 'gpu-driven',
|
|
265
|
+
readonly deviceGeneration: number,
|
|
266
|
+
readonly viewIdentity: 'main:0',
|
|
267
|
+
resourceGeneration: number | undefined,
|
|
268
|
+
) {
|
|
269
|
+
this.resolvedResourceGeneration = resourceGeneration;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
setResourceGeneration(generation: number | undefined): void {
|
|
273
|
+
if (this.state === 'recording') this.resolvedResourceGeneration = generation;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
get resourceGeneration(): number | undefined {
|
|
277
|
+
return this.resolvedResourceGeneration;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
setActualLaneReason(reason: GpuDrivenLaneReason | undefined): void {
|
|
281
|
+
if (this.state === 'recording') this.actualLaneReason = reason;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
record(pass: SurfacePassName, command: SurfaceCommandObservation): void {
|
|
285
|
+
if (this.state !== 'recording') return;
|
|
286
|
+
let recording = this.passes.get(pass);
|
|
287
|
+
if (recording === undefined) {
|
|
288
|
+
recording = { commands: [], totalCommandCount: 0, sawIndirect: false };
|
|
289
|
+
this.passes.set(pass, recording);
|
|
290
|
+
}
|
|
291
|
+
recording.totalCommandCount += 1;
|
|
292
|
+
recording.sawIndirect ||= isIndirect(command);
|
|
293
|
+
if (recording.commands.length >= MAX_COMMANDS_PER_PASS) return;
|
|
294
|
+
const programEvidence =
|
|
295
|
+
command.receiptIdentity === undefined || command.receiptGeneration === undefined
|
|
296
|
+
? 'missing'
|
|
297
|
+
: 'producer-receipt';
|
|
298
|
+
recording.commands.push(Object.freeze({ ...command, programEvidence }));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/** Snapshot consumed only by the readback copy encoded for this candidate. */
|
|
302
|
+
gpuReadbackSnapshot(): SurfaceGpuReadbackSnapshot | undefined {
|
|
303
|
+
if (this.state !== 'submitted') return undefined;
|
|
304
|
+
const passes = (['nearest-layer', 'color'] as const).flatMap((pass) => {
|
|
305
|
+
const recording = this.passes.get(pass);
|
|
306
|
+
if (recording === undefined) return [];
|
|
307
|
+
if (!recording.sawIndirect) return [];
|
|
308
|
+
const ranges = recording.commands.flatMap((command) =>
|
|
309
|
+
isIndirect(command)
|
|
310
|
+
? [
|
|
311
|
+
Object.freeze({
|
|
312
|
+
kind: command.kind,
|
|
313
|
+
indirectBufferIdentity: command.indirectBufferIdentity,
|
|
314
|
+
indirectOffset: command.indirectOffset,
|
|
315
|
+
}),
|
|
316
|
+
]
|
|
317
|
+
: [],
|
|
318
|
+
);
|
|
319
|
+
const savedCommandCount = recording.commands.length;
|
|
320
|
+
return [
|
|
321
|
+
Object.freeze({
|
|
322
|
+
pass,
|
|
323
|
+
totalCommandCount: recording.totalCommandCount,
|
|
324
|
+
savedCommandCount,
|
|
325
|
+
droppedCommandCount: recording.totalCommandCount - savedCommandCount,
|
|
326
|
+
truncated: recording.totalCommandCount > savedCommandCount,
|
|
327
|
+
ranges: Object.freeze(ranges),
|
|
328
|
+
}),
|
|
329
|
+
];
|
|
330
|
+
});
|
|
331
|
+
return Object.freeze({
|
|
332
|
+
sequence: this.sequence,
|
|
333
|
+
frameId: this.frameId,
|
|
334
|
+
deviceGeneration: this.deviceGeneration,
|
|
335
|
+
resourceGeneration: this.resourceGeneration,
|
|
336
|
+
viewIdentity: this.viewIdentity,
|
|
337
|
+
passes: Object.freeze(passes),
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
get laneReason(): GpuDrivenLaneReason | undefined {
|
|
342
|
+
return this.actualLaneReason;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
submit(completed: Promise<unknown>, graphGeneration: number): void {
|
|
346
|
+
if (this.state !== 'recording') return;
|
|
347
|
+
this.state = 'submitted';
|
|
348
|
+
this.owner.submit(this, completed, graphGeneration, this.passes);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
abort(): void {
|
|
352
|
+
if (this.state === 'recording') this.state = 'aborted';
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** Bounded actual-command projection published after the renderer-owned fence. */
|
|
357
|
+
export class SurfaceSubmissionObservationOwner {
|
|
358
|
+
private sequence = 0;
|
|
359
|
+
private acceptedSequence = 0;
|
|
360
|
+
private latest: SurfaceSubmission | undefined;
|
|
361
|
+
|
|
362
|
+
constructor(private readonly currentDeviceGeneration: () => number) {}
|
|
363
|
+
|
|
364
|
+
begin(input: {
|
|
365
|
+
readonly frameId: number;
|
|
366
|
+
readonly requestedLane: 'direct' | 'gpu-driven';
|
|
367
|
+
readonly deviceGeneration: number;
|
|
368
|
+
readonly resourceGeneration: number | undefined;
|
|
369
|
+
}): SurfaceSubmissionCandidate {
|
|
370
|
+
this.sequence += 1;
|
|
371
|
+
return new SurfaceSubmissionCandidate(
|
|
372
|
+
this,
|
|
373
|
+
this.sequence,
|
|
374
|
+
input.frameId,
|
|
375
|
+
input.requestedLane,
|
|
376
|
+
input.deviceGeneration,
|
|
377
|
+
'main:0',
|
|
378
|
+
input.resourceGeneration,
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
inspect(): SurfaceSubmission | undefined {
|
|
383
|
+
return this.latest;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** Attach only selector-visible members copied for this exact completed recording. */
|
|
387
|
+
publishGpuMembers(
|
|
388
|
+
readback: SurfaceGpuMemberReadback | number,
|
|
389
|
+
targetOrLegacyMembers?:
|
|
390
|
+
| { readonly frameId: number; readonly deviceGeneration: number }
|
|
391
|
+
| readonly string[],
|
|
392
|
+
): void {
|
|
393
|
+
// A resource generation alone cannot prove which submit filled the shared
|
|
394
|
+
// readback buffer. Keep the former call shape runtime-compatible but closed.
|
|
395
|
+
const target =
|
|
396
|
+
targetOrLegacyMembers === undefined || Array.isArray(targetOrLegacyMembers)
|
|
397
|
+
? undefined
|
|
398
|
+
: (targetOrLegacyMembers as {
|
|
399
|
+
readonly frameId: number;
|
|
400
|
+
readonly deviceGeneration: number;
|
|
401
|
+
});
|
|
402
|
+
if (typeof readback === 'number' || target === undefined) return;
|
|
403
|
+
const latest = this.latest;
|
|
404
|
+
const recording = readback.recording;
|
|
405
|
+
if (
|
|
406
|
+
latest === undefined ||
|
|
407
|
+
latest.status !== 'completed' ||
|
|
408
|
+
latest.actualLane !== 'gpu-driven' ||
|
|
409
|
+
latest.sequence !== recording.sequence ||
|
|
410
|
+
latest.frameId !== recording.frameId ||
|
|
411
|
+
latest.deviceGeneration !== recording.deviceGeneration ||
|
|
412
|
+
latest.resourceGeneration !== recording.resourceGeneration ||
|
|
413
|
+
latest.viewIdentity !== recording.viewIdentity ||
|
|
414
|
+
latest.frameId !== target.frameId ||
|
|
415
|
+
latest.deviceGeneration !== target.deviceGeneration ||
|
|
416
|
+
latest.passes.length !== recording.passes.length ||
|
|
417
|
+
!latest.passes.every((pass, index) => {
|
|
418
|
+
const snapshot = recording.passes[index];
|
|
419
|
+
return snapshot !== undefined && sameReadbackPass(pass, snapshot);
|
|
420
|
+
})
|
|
421
|
+
) {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (
|
|
425
|
+
readback.indirectParameters === undefined ||
|
|
426
|
+
!sameIndirectParameters(recording, readback.indirectParameters)
|
|
427
|
+
) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
this.latest = Object.freeze({
|
|
431
|
+
...latest,
|
|
432
|
+
passes: Object.freeze(
|
|
433
|
+
latest.passes.map((pass) => {
|
|
434
|
+
const passParameters = readback.indirectParameters?.filter(
|
|
435
|
+
(parameter) => parameter.pass === pass.pass,
|
|
436
|
+
);
|
|
437
|
+
return Object.freeze({
|
|
438
|
+
...pass,
|
|
439
|
+
memberEvidence:
|
|
440
|
+
readback.indirectParameters === undefined
|
|
441
|
+
? ('indirect-readback-required' as const)
|
|
442
|
+
: pass.truncated
|
|
443
|
+
? ('indirect-visible-readback-truncated' as const)
|
|
444
|
+
: ('indirect-visible-readback' as const),
|
|
445
|
+
memberIds: Object.freeze([...readback.memberIds]),
|
|
446
|
+
...(pass.truncated || passParameters === undefined
|
|
447
|
+
? {}
|
|
448
|
+
: { indirectParameters: Object.freeze(passParameters) }),
|
|
449
|
+
});
|
|
450
|
+
}),
|
|
451
|
+
),
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
submit(
|
|
456
|
+
candidate: SurfaceSubmissionCandidate,
|
|
457
|
+
completed: Promise<unknown>,
|
|
458
|
+
graphGeneration: number,
|
|
459
|
+
recordings: ReadonlyMap<SurfacePassName, SurfacePassRecording>,
|
|
460
|
+
): void {
|
|
461
|
+
const sequence = candidate.sequence;
|
|
462
|
+
const passes = (['nearest-layer', 'color'] as const).flatMap((pass) => {
|
|
463
|
+
const recording = recordings.get(pass);
|
|
464
|
+
if (recording === undefined || recording.totalCommandCount === 0) return [];
|
|
465
|
+
const savedCommandCount = recording.commands.length;
|
|
466
|
+
const truncated = recording.totalCommandCount > savedCommandCount;
|
|
467
|
+
return [
|
|
468
|
+
Object.freeze({
|
|
469
|
+
pass,
|
|
470
|
+
commandCount: recording.totalCommandCount,
|
|
471
|
+
totalCommandCount: recording.totalCommandCount,
|
|
472
|
+
savedCommandCount,
|
|
473
|
+
droppedCommandCount: recording.totalCommandCount - savedCommandCount,
|
|
474
|
+
truncated,
|
|
475
|
+
memberEvidence: recording.sawIndirect
|
|
476
|
+
? ('indirect-readback-required' as const)
|
|
477
|
+
: truncated
|
|
478
|
+
? ('direct-command-members-truncated' as const)
|
|
479
|
+
: ('direct-command-members' as const),
|
|
480
|
+
commands: Object.freeze([...recording.commands]),
|
|
481
|
+
}),
|
|
482
|
+
];
|
|
483
|
+
});
|
|
484
|
+
if (passes.length === 0) return;
|
|
485
|
+
const actualLane = [...recordings.values()].some((recording) => recording.sawIndirect)
|
|
486
|
+
? ('gpu-driven' as const)
|
|
487
|
+
: ('direct' as const);
|
|
488
|
+
const submitted = Object.freeze({
|
|
489
|
+
sequence,
|
|
490
|
+
frameId: candidate.frameId,
|
|
491
|
+
requestedLane: candidate.requestedLane,
|
|
492
|
+
actualLane,
|
|
493
|
+
...(candidate.laneReason === undefined ? {} : { actualLaneReason: candidate.laneReason }),
|
|
494
|
+
deviceGeneration: candidate.deviceGeneration,
|
|
495
|
+
graphGeneration,
|
|
496
|
+
viewIdentity: candidate.viewIdentity,
|
|
497
|
+
resourceGeneration: candidate.resourceGeneration,
|
|
498
|
+
status: 'submitted' as const,
|
|
499
|
+
passes: Object.freeze(passes),
|
|
500
|
+
});
|
|
501
|
+
this.latest = submitted;
|
|
502
|
+
void completed.then(
|
|
503
|
+
() => {
|
|
504
|
+
if (
|
|
505
|
+
sequence !== this.sequence ||
|
|
506
|
+
sequence < this.acceptedSequence ||
|
|
507
|
+
this.currentDeviceGeneration() !== candidate.deviceGeneration
|
|
508
|
+
) {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
this.acceptedSequence = sequence;
|
|
512
|
+
this.latest = Object.freeze({ ...submitted, status: 'completed' as const });
|
|
513
|
+
},
|
|
514
|
+
() => undefined,
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
@@ -307,7 +307,10 @@ export function createSkinPaletteAllocator(
|
|
|
307
307
|
if (
|
|
308
308
|
candidate !== undefined &&
|
|
309
309
|
candidate.buffer === storageBuffer &&
|
|
310
|
-
candidate.byteSize >= byteSize
|
|
310
|
+
candidate.byteSize >= byteSize &&
|
|
311
|
+
// Direct/residual draws bind a full palette window even for one joint.
|
|
312
|
+
// A split free range can fit the payload but overrun that binding.
|
|
313
|
+
candidate.offset + BINDING_WINDOW_BYTES <= storageCapacity
|
|
311
314
|
) {
|
|
312
315
|
candidateIndex = index;
|
|
313
316
|
break;
|