@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
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
resolveRenderFeatureDrawBuffers,
|
|
20
20
|
} from './render-graph-raster';
|
|
21
21
|
import { createRenderFeatureGraphBufferState } from './render-graph-resources';
|
|
22
|
+
import type { RenderFeaturePlacement } from './types';
|
|
22
23
|
|
|
23
24
|
export function createRenderFeatureProjectionState() {
|
|
24
25
|
return {
|
|
@@ -141,6 +142,10 @@ export function projectRenderFeaturePlans<FrameCtx extends RenderGraphFrame>(
|
|
|
141
142
|
readonly reportError?: ((error: RenderError) => void) | undefined;
|
|
142
143
|
readonly resolveStandardLighting?: RenderFeatureLightingResolver<FrameCtx> | undefined;
|
|
143
144
|
readonly standardSurfaceAccesses?: readonly GraphAccess[] | undefined;
|
|
145
|
+
/** Restrict projection to one Standard graph placement. */
|
|
146
|
+
readonly placement?: RenderFeaturePlacement | undefined;
|
|
147
|
+
/** Restrict projection to the named passes for a multi-stage feature. */
|
|
148
|
+
readonly passNames?: ReadonlySet<string> | undefined;
|
|
144
149
|
readonly state?: ReturnType<typeof createRenderFeatureProjectionState>;
|
|
145
150
|
},
|
|
146
151
|
): Result<void, RenderGraphError | RenderError> {
|
|
@@ -162,7 +167,11 @@ export function projectRenderFeaturePlans<FrameCtx extends RenderGraphFrame>(
|
|
|
162
167
|
options.standardSurfaceAccesses,
|
|
163
168
|
);
|
|
164
169
|
for (const execution of executions) {
|
|
170
|
+
if (options.placement !== undefined && (execution.placement ?? 'post') !== options.placement) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
165
173
|
for (const pass of execution.passes) {
|
|
174
|
+
if (options.passNames !== undefined && !options.passNames.has(pass.name)) continue;
|
|
166
175
|
if (state.projected.has(pass)) continue;
|
|
167
176
|
if (pass.shadowCaster)
|
|
168
177
|
return err(
|
|
@@ -57,6 +57,7 @@ export type RenderFeatureGraphBindingsResolver<FrameCtx extends RenderGraphFrame
|
|
|
57
57
|
readonly binding: Extract<PreparedGraphicsResolvedResource, { readonly kind: 'bindings' }>;
|
|
58
58
|
readonly resources: GraphResourceResolver;
|
|
59
59
|
readonly resolveTarget: RenderFeatureGraphTargetResolver;
|
|
60
|
+
readonly resolveGpuResource?: (name: string) => RenderFeatureResolvedGpuBuffer | undefined;
|
|
60
61
|
}) => RenderFeatureGraphBindingsResolution | undefined;
|
|
61
62
|
|
|
62
63
|
export type RenderFeatureLightingResolver<FrameCtx extends RenderGraphFrame> = (
|
|
@@ -275,6 +276,32 @@ export class RenderFeatureRasterGraphProjection<FrameCtx extends RenderGraphFram
|
|
|
275
276
|
accesses.push({ resource: handle, usage: 'indirect-read' } as const);
|
|
276
277
|
}
|
|
277
278
|
|
|
279
|
+
// Feature-owned fullscreen/material bind groups may carry a read-only
|
|
280
|
+
// storage buffer (for example the bounded procedural cloud cache). Import
|
|
281
|
+
// it into the same graph so the compute producer is ordered before the
|
|
282
|
+
// raster consumer and the buffer lease follows queue retirement.
|
|
283
|
+
for (const draw of descriptor.draws) {
|
|
284
|
+
for (const reference of draw.bindings) {
|
|
285
|
+
const binding = resolved(snapshot, reference);
|
|
286
|
+
const names =
|
|
287
|
+
binding?.kind === 'bindings' ? binding.descriptor?.values.storageBuffers : undefined;
|
|
288
|
+
if (!Array.isArray(names)) continue;
|
|
289
|
+
for (const name of names) {
|
|
290
|
+
if (typeof name !== 'string') continue;
|
|
291
|
+
const physical = snapshot.resolveGpuResource?.(name);
|
|
292
|
+
if (physical === undefined) continue;
|
|
293
|
+
const imported = importRenderFeatureGraphBuffer(
|
|
294
|
+
this.builder,
|
|
295
|
+
this.buffers,
|
|
296
|
+
`${name}.${featureIdentity}.${order}`,
|
|
297
|
+
physical,
|
|
298
|
+
);
|
|
299
|
+
if (!imported.ok) return imported;
|
|
300
|
+
accesses.push({ resource: imported.value, usage: 'storage-read' } as const);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
278
305
|
return this.builder.addRasterPass(name, {
|
|
279
306
|
accesses,
|
|
280
307
|
colorAttachments: colors,
|
|
@@ -377,9 +404,24 @@ export class RenderFeatureRasterGraphProjection<FrameCtx extends RenderGraphFram
|
|
|
377
404
|
pass.setBindGroup(0, shadowView, [0, 0]);
|
|
378
405
|
continue;
|
|
379
406
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
407
|
+
// Fullscreen feature bindings contain graph-owned texture views and a
|
|
408
|
+
// per-frame params UBO. Resolve them at execution time so a retained
|
|
409
|
+
// graph still follows the current post-process input and authored
|
|
410
|
+
// parameters; material/view bindings remain safely cached.
|
|
411
|
+
const resolvedBindings = (() => {
|
|
412
|
+
const resolve = () =>
|
|
413
|
+
this.resolveBindings?.({
|
|
414
|
+
frame,
|
|
415
|
+
binding,
|
|
416
|
+
resources,
|
|
417
|
+
resolveTarget: this.resolveTarget,
|
|
418
|
+
...(snapshot.resolveGpuResource === undefined
|
|
419
|
+
? {}
|
|
420
|
+
: { resolveGpuResource: snapshot.resolveGpuResource }),
|
|
421
|
+
});
|
|
422
|
+
if (binding.descriptor?.values.fullscreen === true) return resolve();
|
|
423
|
+
return binding.handle ?? resolve();
|
|
424
|
+
})();
|
|
383
425
|
const handle =
|
|
384
426
|
resolvedBindings !== undefined &&
|
|
385
427
|
typeof resolvedBindings === 'object' &&
|
package/src/features/targets.ts
CHANGED
|
@@ -55,6 +55,8 @@ export function resolveStandardRenderFeatureTargets(input: {
|
|
|
55
55
|
readonly storageBuffer: boolean;
|
|
56
56
|
readonly multisample: boolean;
|
|
57
57
|
readonly colorAttachmentFormat: TextureFormat;
|
|
58
|
+
/** Expose cloud history aliases only while a CloudLayer is authored. */
|
|
59
|
+
readonly cloudHistory?: boolean;
|
|
58
60
|
}): readonly RenderFeatureTargetHandle[] {
|
|
59
61
|
const sampleCount: 1 | 4 = input.antialias === 'msaa' && input.multisample ? 4 : 1;
|
|
60
62
|
// Standard always exposes the scene to features as a linear float target;
|
|
@@ -91,5 +93,69 @@ export function resolveStandardRenderFeatureTargets(input: {
|
|
|
91
93
|
format: colorFormat,
|
|
92
94
|
sampleCount: 1,
|
|
93
95
|
}),
|
|
96
|
+
// A graph-owned, single-sample map produced before direct-solar lighting.
|
|
97
|
+
// The logical handle lets the feature plan validate its producer before
|
|
98
|
+
// the Standard pipeline allocates the concrete texture.
|
|
99
|
+
createRenderFeatureTarget({
|
|
100
|
+
name: 'cloud-shadow',
|
|
101
|
+
kind: 'scene-color',
|
|
102
|
+
format: 'rgba16float',
|
|
103
|
+
sampleCount: 1,
|
|
104
|
+
}),
|
|
105
|
+
// These are declarative aliases only. Standard allocates the actual
|
|
106
|
+
// linear-LDR ping-pong target at the ordered post stage and resolves these
|
|
107
|
+
// names through `contributeFeatures` when that stage is reached.
|
|
108
|
+
createRenderFeatureTarget({
|
|
109
|
+
name: 'barrel-input',
|
|
110
|
+
kind: 'scene-color',
|
|
111
|
+
format: 'rgba16float',
|
|
112
|
+
sampleCount: 1,
|
|
113
|
+
}),
|
|
114
|
+
createRenderFeatureTarget({
|
|
115
|
+
name: 'barrel-output',
|
|
116
|
+
kind: 'scene-color',
|
|
117
|
+
format: 'rgba16float',
|
|
118
|
+
sampleCount: 1,
|
|
119
|
+
}),
|
|
120
|
+
...(input.cloudHistory === true
|
|
121
|
+
? [
|
|
122
|
+
createRenderFeatureTarget({
|
|
123
|
+
name: 'cloud-history-radiance-previous',
|
|
124
|
+
kind: 'scene-color',
|
|
125
|
+
format: 'rgba16float',
|
|
126
|
+
sampleCount: 1,
|
|
127
|
+
}),
|
|
128
|
+
createRenderFeatureTarget({
|
|
129
|
+
name: 'cloud-history-radiance-current',
|
|
130
|
+
kind: 'scene-color',
|
|
131
|
+
format: 'rgba16float',
|
|
132
|
+
sampleCount: 1,
|
|
133
|
+
}),
|
|
134
|
+
createRenderFeatureTarget({
|
|
135
|
+
name: 'cloud-history-transmittance-previous',
|
|
136
|
+
kind: 'scene-color',
|
|
137
|
+
format: 'rgba16float',
|
|
138
|
+
sampleCount: 1,
|
|
139
|
+
}),
|
|
140
|
+
createRenderFeatureTarget({
|
|
141
|
+
name: 'cloud-history-transmittance-current',
|
|
142
|
+
kind: 'scene-color',
|
|
143
|
+
format: 'rgba16float',
|
|
144
|
+
sampleCount: 1,
|
|
145
|
+
}),
|
|
146
|
+
createRenderFeatureTarget({
|
|
147
|
+
name: 'cloud-history-depth-previous',
|
|
148
|
+
kind: 'scene-color',
|
|
149
|
+
format: 'rgba16float',
|
|
150
|
+
sampleCount: 1,
|
|
151
|
+
}),
|
|
152
|
+
createRenderFeatureTarget({
|
|
153
|
+
name: 'cloud-history-depth-current',
|
|
154
|
+
kind: 'scene-color',
|
|
155
|
+
format: 'rgba16float',
|
|
156
|
+
sampleCount: 1,
|
|
157
|
+
}),
|
|
158
|
+
]
|
|
159
|
+
: []),
|
|
94
160
|
];
|
|
95
161
|
}
|
package/src/features/types.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { RhiCaps } from '@forgeax/engine-rhi';
|
|
|
4
4
|
import type { Result } from '@forgeax/engine-types';
|
|
5
5
|
import type { RenderError, RenderFeatureErrorDescriptor } from '../errors/render';
|
|
6
6
|
import type { VisibilitySnapshot } from '../extract/visibility';
|
|
7
|
+
import type { CameraSnapshot } from '../render-contract';
|
|
7
8
|
import type { RenderFeaturePlan, RenderFeaturePlanContext } from './plan';
|
|
8
9
|
import type { RenderFeatureCapabilityKey } from './vocabulary';
|
|
9
10
|
|
|
@@ -42,6 +43,17 @@ export type {
|
|
|
42
43
|
/** Closed lifecycle states exposed by the feature host. */
|
|
43
44
|
export type RenderFeatureStatus = 'active' | 'failed' | 'disabled' | 'disposed';
|
|
44
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Graph placement for a producer-owned feature.
|
|
48
|
+
*
|
|
49
|
+
* `scene` is admitted after the opaque scene and before transmission,
|
|
50
|
+
* ordinary transparency, and volumetric composition. `post` is admitted at
|
|
51
|
+
* the existing post-TAA extension point. Keeping this as one closed value
|
|
52
|
+
* lets the Standard owner place atmospheric transport without adding a
|
|
53
|
+
* second renderer or a feature-specific side channel.
|
|
54
|
+
*/
|
|
55
|
+
export type RenderFeaturePlacement = 'scene' | 'post';
|
|
56
|
+
|
|
45
57
|
/**
|
|
46
58
|
* Shader preparation policy for feature-owned GPU programs.
|
|
47
59
|
*
|
|
@@ -63,6 +75,27 @@ export interface RenderFeatureWorldVisibilitySnapshot {
|
|
|
63
75
|
readonly snapshot: VisibilitySnapshot;
|
|
64
76
|
}
|
|
65
77
|
|
|
78
|
+
/** Renderer-owned view facts shared by feature extraction and temporal owners. */
|
|
79
|
+
export interface RenderFeatureViewContext {
|
|
80
|
+
readonly identity: string;
|
|
81
|
+
readonly width: number;
|
|
82
|
+
readonly height: number;
|
|
83
|
+
readonly cameraRevision: number;
|
|
84
|
+
readonly deviceGeneration: number;
|
|
85
|
+
readonly cameraPosition: readonly [number, number, number];
|
|
86
|
+
/** Stable world anchor for light-space cloud coverage (never screen-space). */
|
|
87
|
+
readonly shadowAnchor?: readonly [number, number, number];
|
|
88
|
+
readonly cameraCut?: boolean;
|
|
89
|
+
readonly recovery?: boolean;
|
|
90
|
+
readonly sceneDepthVersion?: number;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Normal frame projection consumed by feature owners at extract time. */
|
|
94
|
+
export interface RenderFeatureFrameContext {
|
|
95
|
+
readonly cloudLayer?: import('../cloud/extract').ExtractedCloudLayer;
|
|
96
|
+
readonly view?: RenderFeatureViewContext;
|
|
97
|
+
}
|
|
98
|
+
|
|
66
99
|
/** A producer's structured report for one hidden render candidate. */
|
|
67
100
|
export interface RenderFeatureHiddenEntityReport {
|
|
68
101
|
readonly world: World;
|
|
@@ -73,6 +106,16 @@ export interface RenderFeatureExtractContext {
|
|
|
73
106
|
readonly worlds: readonly World[];
|
|
74
107
|
readonly owner: number;
|
|
75
108
|
readonly frameNumber: number;
|
|
109
|
+
/**
|
|
110
|
+
* Renderer-selected display camera for this frame. Features that affect the
|
|
111
|
+
* display must derive their active plan from this snapshot instead of
|
|
112
|
+
* scanning every Camera in the composed worlds.
|
|
113
|
+
*/
|
|
114
|
+
readonly selectedCamera?: CameraSnapshot;
|
|
115
|
+
/** Renderer capability facts for source extraction and inspect projections. */
|
|
116
|
+
readonly caps?: Readonly<RhiCaps>;
|
|
117
|
+
/** Normal frame-owner projection; feature code must consume this snapshot. */
|
|
118
|
+
readonly frame?: RenderFeatureFrameContext;
|
|
76
119
|
/** Same-batch World snapshots; absent for synthetic direct feature probes. */
|
|
77
120
|
readonly visibilitySnapshots?: readonly RenderFeatureWorldVisibilitySnapshot[];
|
|
78
121
|
/** Host-owned report sink; feature code never owns the merged diagnostic. */
|
|
@@ -106,6 +149,8 @@ export interface RenderFeatureSubmission {
|
|
|
106
149
|
*/
|
|
107
150
|
export interface RenderFeature<FrameData> {
|
|
108
151
|
readonly identity: string;
|
|
152
|
+
/** Optional graph placement; omitted features retain the historical post stage. */
|
|
153
|
+
readonly placement?: RenderFeaturePlacement;
|
|
109
154
|
readonly requiredCapabilities?: readonly RenderFeatureCapabilityKey[];
|
|
110
155
|
/** Optional feature-owned shader preparation policy; defaults to `validated`. */
|
|
111
156
|
readonly shaderModuleMode?: RenderFeatureShaderModuleMode;
|
|
@@ -151,4 +196,6 @@ export interface RenderFeatureDiagnostics {
|
|
|
151
196
|
readonly order: number;
|
|
152
197
|
readonly status: RenderFeatureStatus;
|
|
153
198
|
readonly latestError: RenderFeatureErrorDescriptor | undefined;
|
|
199
|
+
/** Optional producer-owned detached inspection snapshot from the latest extract. */
|
|
200
|
+
readonly inspection?: unknown;
|
|
154
201
|
}
|
|
@@ -48,14 +48,14 @@ const FULLSCREEN_DEFAULT_SPEC: PipelineSpec = Object.freeze({
|
|
|
48
48
|
/**
|
|
49
49
|
* Declared sample type for a post-process read entry.
|
|
50
50
|
*
|
|
51
|
-
* Closed union (plan-strategy D-7):
|
|
52
|
-
*
|
|
53
|
-
*
|
|
51
|
+
* Closed union (plan-strategy D-7): `'depth'` identifies a depth input and
|
|
52
|
+
* `'multisampled-float'` identifies the explicit 4x paired-resolve color
|
|
53
|
+
* input. Color inputs otherwise use the default bare string / `{ key }` form.
|
|
54
54
|
*
|
|
55
55
|
* AI-user affordance: IDE autocomplete exposes `'depth'` at the register call
|
|
56
56
|
* site; misspellings are caught by the type system (AC-08).
|
|
57
57
|
*/
|
|
58
|
-
export type PostProcessReadSampleType = 'depth';
|
|
58
|
+
export type PostProcessReadSampleType = 'depth' | 'multisampled-float';
|
|
59
59
|
|
|
60
60
|
// ─── Post-process shader entry (owned by the fullscreen feature host) ──────
|
|
61
61
|
|
|
@@ -105,6 +105,10 @@ export interface PostProcessShaderEntry {
|
|
|
105
105
|
* represent a color input (plan-strategy D-1 / D-7).
|
|
106
106
|
*/
|
|
107
107
|
readonly reads?: readonly (string | PostProcessReadEntry)[] | undefined;
|
|
108
|
+
/** Use the renderer-owned View bind group at group(0). */
|
|
109
|
+
readonly usesView?: boolean | undefined;
|
|
110
|
+
/** Read-only storage buffers appended to the fullscreen bind group. */
|
|
111
|
+
readonly storageBindings?: readonly number[] | undefined;
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
function postProcessSourceDigest(source: string): string {
|
|
@@ -124,8 +128,10 @@ export function postProcessShaderPipelineLabel(identity: string, source: string)
|
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
/** Content-addressed shader-module label shared by prewarm and lazy paths. */
|
|
127
|
-
export function postProcessShaderModuleLabel(
|
|
128
|
-
|
|
131
|
+
export function postProcessShaderModuleLabel(source: string): string {
|
|
132
|
+
// Graph-local names and public feature identities may alias the same source.
|
|
133
|
+
// Share the prewarmed module, while pipelines retain their own layouts/targets.
|
|
134
|
+
return `post-process-module-${postProcessSourceDigest(source)}`;
|
|
129
135
|
}
|
|
130
136
|
|
|
131
137
|
/**
|
|
@@ -145,6 +151,8 @@ export function postProcessShaderEntrySignature(entry: PostProcessShaderEntry):
|
|
|
145
151
|
defaultValue: Array.from(entry.params.defaultValue),
|
|
146
152
|
},
|
|
147
153
|
reads: entry.reads,
|
|
154
|
+
usesView: entry.usesView,
|
|
155
|
+
storageBindings: entry.storageBindings,
|
|
148
156
|
});
|
|
149
157
|
}
|
|
150
158
|
|
|
@@ -161,8 +169,8 @@ export function isTemporalFullscreenBinding(values: Readonly<Record<string, unkn
|
|
|
161
169
|
* Structured read entry for a post-process shader.
|
|
162
170
|
*
|
|
163
171
|
* `key` is the graph resource key (matching a graph color target).
|
|
164
|
-
* `sampleType` is an optional type discriminant (D-1 SSOT); when omitted
|
|
165
|
-
*
|
|
172
|
+
* `sampleType` is an optional type discriminant (D-1 SSOT); when omitted the
|
|
173
|
+
* entry is treated as a single-sample color input (same as a bare string).
|
|
166
174
|
*/
|
|
167
175
|
export interface PostProcessReadEntry {
|
|
168
176
|
readonly key: string;
|
|
@@ -307,6 +315,7 @@ export function buildFullscreenPostProcessPass(
|
|
|
307
315
|
sampler: Sampler | null;
|
|
308
316
|
depthSampler: Sampler | null;
|
|
309
317
|
extraColorBindings: readonly number[];
|
|
318
|
+
extraStorageBindings: readonly number[];
|
|
310
319
|
createHandle: (
|
|
311
320
|
name: string,
|
|
312
321
|
pipeline: unknown,
|
|
@@ -327,9 +336,14 @@ export function buildFullscreenPostProcessPass(
|
|
|
327
336
|
// texture variant for a 4-sample scene target. params@2 is always present to
|
|
328
337
|
// avoid 2x2 kind explosion.
|
|
329
338
|
const hasDepth = entryHasDepthRead(entry);
|
|
339
|
+
const hasMultisampledColor = (entry.reads ?? []).some(
|
|
340
|
+
(read) => typeof read !== 'string' && read.sampleType === 'multisampled-float',
|
|
341
|
+
);
|
|
330
342
|
const bglKind: BglKind = hasDepth
|
|
331
343
|
? depthMultisampled
|
|
332
|
-
?
|
|
344
|
+
? hasMultisampledColor
|
|
345
|
+
? 'fullscreen-post-with-paired-msaa'
|
|
346
|
+
: 'fullscreen-post-with-scene-depth-msaa'
|
|
333
347
|
: 'fullscreen-post-with-scene-depth'
|
|
334
348
|
: entry.params !== undefined
|
|
335
349
|
? 'fullscreen-post-with-params'
|
|
@@ -347,6 +361,14 @@ export function buildFullscreenPostProcessPass(
|
|
|
347
361
|
texture: { sampleType: 'float', viewDimension: '2d' },
|
|
348
362
|
});
|
|
349
363
|
}
|
|
364
|
+
const firstStorageBinding = firstExtraBinding + extraColorCount;
|
|
365
|
+
for (const [index, binding] of (entry.storageBindings ?? []).entries()) {
|
|
366
|
+
descriptor.entries.push({
|
|
367
|
+
binding: binding ?? firstStorageBinding + index,
|
|
368
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
369
|
+
buffer: { type: 'read-only-storage' },
|
|
370
|
+
});
|
|
371
|
+
}
|
|
350
372
|
const bglRes = device.createBindGroupLayout(descriptor);
|
|
351
373
|
if (!bglRes.ok) {
|
|
352
374
|
ctx.errorRegistry.fire(bglRes.error);
|
|
@@ -364,6 +386,9 @@ export function buildFullscreenPostProcessPass(
|
|
|
364
386
|
extraColorBindings: Object.freeze(
|
|
365
387
|
Array.from({ length: extraColorCount }, (_, index) => firstExtraBinding + index),
|
|
366
388
|
),
|
|
389
|
+
extraStorageBindings: Object.freeze(
|
|
390
|
+
(entry.storageBindings ?? []).map((binding, index) => binding ?? firstStorageBinding + index),
|
|
391
|
+
),
|
|
367
392
|
createHandle: (name, pipeline, paramsBuffer) => ({
|
|
368
393
|
name,
|
|
369
394
|
paramsBuffer,
|
|
@@ -402,6 +427,7 @@ export function createFullscreenBindGroup(
|
|
|
402
427
|
depthTexView?: TextureView | null,
|
|
403
428
|
depthSampler?: Sampler | null,
|
|
404
429
|
additionalViews: readonly { readonly binding: number; readonly view: TextureView }[] = [],
|
|
430
|
+
additionalBuffers: readonly { readonly binding: number; readonly buffer: Buffer }[] = [],
|
|
405
431
|
): BindGroup | null {
|
|
406
432
|
const entries: { binding: number; resource: { kind: string; value: unknown } }[] = [
|
|
407
433
|
{ binding: 0, resource: { kind: 'textureView', value: inputView } },
|
|
@@ -427,6 +453,12 @@ export function createFullscreenBindGroup(
|
|
|
427
453
|
resource: { kind: 'textureView', value: additional.view },
|
|
428
454
|
});
|
|
429
455
|
}
|
|
456
|
+
for (const additional of additionalBuffers) {
|
|
457
|
+
entries.push({
|
|
458
|
+
binding: additional.binding,
|
|
459
|
+
resource: { kind: 'buffer', value: { buffer: additional.buffer } },
|
|
460
|
+
});
|
|
461
|
+
}
|
|
430
462
|
const res = device.createBindGroup({
|
|
431
463
|
label: 'fullscreen-post-process-bg',
|
|
432
464
|
layout: bgl,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Renderer-local linear ordering of fixed-width GPU row addresses. */
|
|
2
|
+
export class GpuDirtyRanges {
|
|
3
|
+
private first = new Uint32Array(0);
|
|
4
|
+
private second = new Uint32Array(0);
|
|
5
|
+
private readonly counts = new Uint32Array(256);
|
|
6
|
+
|
|
7
|
+
coalesce(slots: readonly number[]): readonly { readonly start: number; readonly end: number }[] {
|
|
8
|
+
if (slots.length === 0) return [];
|
|
9
|
+
if (slots.length > this.first.length) {
|
|
10
|
+
const capacity = 2 ** Math.ceil(Math.log2(slots.length));
|
|
11
|
+
this.first = new Uint32Array(capacity);
|
|
12
|
+
this.second = new Uint32Array(capacity);
|
|
13
|
+
}
|
|
14
|
+
this.first.set(slots);
|
|
15
|
+
let source = this.first;
|
|
16
|
+
let target = this.second;
|
|
17
|
+
for (let shift = 0; shift < 32; shift += 8) {
|
|
18
|
+
this.counts.fill(0);
|
|
19
|
+
for (let i = 0; i < slots.length; i++) {
|
|
20
|
+
const bucket = ((source[i] ?? 0) >>> shift) & 255;
|
|
21
|
+
this.counts[bucket] = (this.counts[bucket] ?? 0) + 1;
|
|
22
|
+
}
|
|
23
|
+
let offset = 0;
|
|
24
|
+
for (let i = 0; i < 256; i++) {
|
|
25
|
+
const count = this.counts[i] ?? 0;
|
|
26
|
+
this.counts[i] = offset;
|
|
27
|
+
offset += count;
|
|
28
|
+
}
|
|
29
|
+
for (let i = 0; i < slots.length; i++) {
|
|
30
|
+
const value = source[i] ?? 0;
|
|
31
|
+
const bucket = (value >>> shift) & 255;
|
|
32
|
+
const index = this.counts[bucket] ?? 0;
|
|
33
|
+
target[index] = value;
|
|
34
|
+
this.counts[bucket] = index + 1;
|
|
35
|
+
}
|
|
36
|
+
[source, target] = [target, source];
|
|
37
|
+
}
|
|
38
|
+
const ranges: { start: number; end: number }[] = [];
|
|
39
|
+
for (let i = 0; i < slots.length; i++) {
|
|
40
|
+
const slot = source[i] ?? 0;
|
|
41
|
+
const previous = ranges.at(-1);
|
|
42
|
+
if (previous !== undefined && slot <= previous.end)
|
|
43
|
+
previous.end = Math.max(previous.end, slot + 1);
|
|
44
|
+
else ranges.push({ start: slot, end: slot + 1 });
|
|
45
|
+
}
|
|
46
|
+
return ranges;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -28,6 +28,8 @@ export interface GpuDrivenBatchKey {
|
|
|
28
28
|
readonly resourceIdentity?: string;
|
|
29
29
|
/** Closed admission lane for the prepared Standard PBR draw. */
|
|
30
30
|
readonly admission?: 'opaque' | 'alpha-mask';
|
|
31
|
+
/** Graph lane that owns this material after the G-buffer projection. */
|
|
32
|
+
readonly materialPass?: 'deferred' | 'forward-only';
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
export interface GpuDrivenCandidate {
|
|
@@ -66,6 +68,52 @@ export interface SubmissionPlan {
|
|
|
66
68
|
readonly visibleCapacity: number;
|
|
67
69
|
}
|
|
68
70
|
|
|
71
|
+
export interface ResourceClassSplitInspection {
|
|
72
|
+
readonly resourceClassCount: number;
|
|
73
|
+
readonly resourceClassSplits: readonly {
|
|
74
|
+
readonly resourceIdentity: string;
|
|
75
|
+
readonly batchIds: readonly number[];
|
|
76
|
+
readonly candidateCount: number;
|
|
77
|
+
}[];
|
|
78
|
+
readonly resourceClassSplitReasons: readonly string[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Attribute batch splits to the prepared resource identity. Draw ranges and
|
|
83
|
+
* dynamic page ranges are deliberately absent from this grouping, so they can
|
|
84
|
+
* never be reported as a resource-class split.
|
|
85
|
+
*/
|
|
86
|
+
export function inspectResourceClassSplits(
|
|
87
|
+
plan: Pick<SubmissionPlan, 'batches'>,
|
|
88
|
+
): ResourceClassSplitInspection {
|
|
89
|
+
const groups = new Map<string, { readonly batchIds: number[]; candidateCount: number }>();
|
|
90
|
+
for (const batch of plan.batches) {
|
|
91
|
+
const resourceIdentity = batch.key.resourceIdentity ?? batch.key.materialResourceClass;
|
|
92
|
+
const group = groups.get(resourceIdentity) ?? { batchIds: [], candidateCount: 0 };
|
|
93
|
+
group.batchIds.push(batch.batchId);
|
|
94
|
+
group.candidateCount += batch.candidates.length;
|
|
95
|
+
groups.set(resourceIdentity, group);
|
|
96
|
+
}
|
|
97
|
+
const resourceClassSplits = [...groups.entries()]
|
|
98
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
99
|
+
.map(([resourceIdentity, group]) =>
|
|
100
|
+
Object.freeze({
|
|
101
|
+
resourceIdentity,
|
|
102
|
+
batchIds: Object.freeze([...group.batchIds].sort((left, right) => left - right)),
|
|
103
|
+
candidateCount: group.candidateCount,
|
|
104
|
+
}),
|
|
105
|
+
);
|
|
106
|
+
const resourceClassSplitReasons =
|
|
107
|
+
resourceClassSplits.length <= 1
|
|
108
|
+
? []
|
|
109
|
+
: resourceClassSplits.map(({ resourceIdentity }) => `resource-class:${resourceIdentity}`);
|
|
110
|
+
return Object.freeze({
|
|
111
|
+
resourceClassCount: resourceClassSplits.length,
|
|
112
|
+
resourceClassSplits: Object.freeze(resourceClassSplits),
|
|
113
|
+
resourceClassSplitReasons: Object.freeze(resourceClassSplitReasons),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
69
117
|
export interface GpuLodCandidateInput {
|
|
70
118
|
readonly candidate: GpuDrivenCandidate;
|
|
71
119
|
readonly rows: readonly GpuLodRow[];
|
|
@@ -298,6 +346,7 @@ function eligibleDraws(slot: RenderSceneSlot): readonly EligibleGpuDrivenDraw[]
|
|
|
298
346
|
preparedIdentity,
|
|
299
347
|
resourceIdentity: draw.materialResourceClass,
|
|
300
348
|
admission,
|
|
349
|
+
materialPass: material.deferredPass === true ? 'deferred' : 'forward-only',
|
|
301
350
|
},
|
|
302
351
|
prepared,
|
|
303
352
|
...candidatePayload(draw, snapshot),
|
|
@@ -657,6 +706,7 @@ export class BatchTopology {
|
|
|
657
706
|
inspect(): BatchTopologyInspection {
|
|
658
707
|
let candidateCount = 0;
|
|
659
708
|
for (const batch of this.batches.values()) candidateCount += batch.candidates.size;
|
|
709
|
+
const resourceClasses = inspectResourceClassSplits(this.plan());
|
|
660
710
|
return {
|
|
661
711
|
revision: this.revision,
|
|
662
712
|
batchCount: this.batches.size,
|
|
@@ -669,6 +719,9 @@ export class BatchTopology {
|
|
|
669
719
|
membershipAllocations: this.membershipAllocations,
|
|
670
720
|
candidateAdds: this.candidateAdds,
|
|
671
721
|
candidateRemoves: this.candidateRemoves,
|
|
722
|
+
resourceClassCount: resourceClasses.resourceClassCount,
|
|
723
|
+
resourceClassSplits: resourceClasses.resourceClassSplits,
|
|
724
|
+
resourceClassSplitReasons: resourceClasses.resourceClassSplitReasons,
|
|
672
725
|
};
|
|
673
726
|
}
|
|
674
727
|
|
|
@@ -6,6 +6,18 @@ import { hasRequiredVertexInputs } from './prepared-draw';
|
|
|
6
6
|
|
|
7
7
|
type ArtifactRow = { readonly source: RenderableSnapshot; readonly renderableIndex: number };
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the producer fact that group(3) binding(1) needs a ProbeBlend page.
|
|
11
|
+
* Single-layer medium artifacts are compiled with the ProbeBlend ABI even
|
|
12
|
+
* when their runtime artifact variantSet is intentionally absent.
|
|
13
|
+
*/
|
|
14
|
+
export function requiresProbeBlendRecord(artifact: MaterialShaderArtifact): boolean {
|
|
15
|
+
return (
|
|
16
|
+
artifact.variantSet?.includes('PROBE_BLEND_AVAILABLE=true') === true ||
|
|
17
|
+
artifact.receipt?.surface?.model === 'single-layer-medium'
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
9
21
|
/** Resolve the same producer programs for normal frames and replacement devices. */
|
|
10
22
|
export function collectGpuDrivenMaterialArtifacts({
|
|
11
23
|
rows,
|
|
@@ -26,7 +38,7 @@ export function collectGpuDrivenMaterialArtifacts({
|
|
|
26
38
|
}) {
|
|
27
39
|
const materialArtifacts = new Map<string, MaterialShaderArtifact>();
|
|
28
40
|
const shadowMaterialArtifacts = new Map<string, MaterialShaderArtifact>();
|
|
29
|
-
const
|
|
41
|
+
const shadowProgramEntries = new Map<string, DispatchEntry>();
|
|
30
42
|
const forwardProgramEntries = new Map<
|
|
31
43
|
string,
|
|
32
44
|
{ readonly vertexEntry?: string; readonly fragmentEntry?: string }
|
|
@@ -42,10 +54,7 @@ export function collectGpuDrivenMaterialArtifacts({
|
|
|
42
54
|
}
|
|
43
55
|
for (const entry of shadowDispatch) {
|
|
44
56
|
if (entry.tags.LightMode !== 'ShadowCaster' || entry.materialShaderId === undefined) continue;
|
|
45
|
-
|
|
46
|
-
`${entry.renderableIndex}:${entry.materialHandle}`,
|
|
47
|
-
entry.materialShaderId,
|
|
48
|
-
);
|
|
57
|
+
shadowProgramEntries.set(`${entry.renderableIndex}:${entry.materialHandle}`, entry);
|
|
49
58
|
}
|
|
50
59
|
const collectArtifacts = (
|
|
51
60
|
rows: readonly ArtifactRow[],
|
|
@@ -58,20 +67,26 @@ export function collectGpuDrivenMaterialArtifacts({
|
|
|
58
67
|
const prepared = draw.prepared;
|
|
59
68
|
if (prepared === undefined) continue;
|
|
60
69
|
const material = row.source.materials[draw.materialSlot] ?? row.source.material;
|
|
70
|
+
const programKey = `${row.renderableIndex}:${material.materialHandle ?? -1}`;
|
|
71
|
+
// Keep program identity and entry points on the same selected dispatch.
|
|
72
|
+
// Looking this up per draw must not scan the scene's dispatch roster.
|
|
73
|
+
const shadowProgramEntry = shadowProgramEntries.get(programKey);
|
|
61
74
|
const logicalMaterialShaderId = material.materialShaderId ?? prepared.identity.material;
|
|
62
75
|
const sceneIndexProgramKeys = material.materialSceneIndexProgramKeys;
|
|
63
76
|
const directMaterialShaderId =
|
|
64
|
-
pass === 'shadow'
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
pass === 'shadow' ? shadowProgramEntry?.materialShaderId : logicalMaterialShaderId;
|
|
78
|
+
let sceneIndexProgramKey: string | undefined;
|
|
79
|
+
for (const passName in sceneIndexProgramKeys) {
|
|
80
|
+
const program = sceneIndexProgramKeys[passName];
|
|
81
|
+
if (
|
|
82
|
+
program?.pass === pass &&
|
|
83
|
+
directMaterialShaderId !== undefined &&
|
|
84
|
+
material.materialProgramKeys?.[passName] === directMaterialShaderId
|
|
85
|
+
) {
|
|
86
|
+
sceneIndexProgramKey = program.specializationKey;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
75
90
|
// A modern publication may expose a scene-index pair for its
|
|
76
91
|
// forward Pass but omit ShadowCaster. Keep that material on its
|
|
77
92
|
// explicit CPU shadow lane; do not reinterpret its direct WGSL
|
|
@@ -82,7 +97,7 @@ export function collectGpuDrivenMaterialArtifacts({
|
|
|
82
97
|
const materialShaderId =
|
|
83
98
|
pass === 'shadow'
|
|
84
99
|
? (sceneIndexProgramKey ??
|
|
85
|
-
|
|
100
|
+
shadowProgramEntry?.materialShaderId ??
|
|
86
101
|
logicalMaterialShaderId)
|
|
87
102
|
: (sceneIndexProgramKey ?? logicalMaterialShaderId);
|
|
88
103
|
const artifact = resolve(materialShaderId, {
|
|
@@ -98,14 +113,7 @@ export function collectGpuDrivenMaterialArtifacts({
|
|
|
98
113
|
: {}),
|
|
99
114
|
});
|
|
100
115
|
const programEntry =
|
|
101
|
-
pass === 'shadow'
|
|
102
|
-
? shadowDispatch.find(
|
|
103
|
-
(entry) =>
|
|
104
|
-
entry.tags.LightMode === 'ShadowCaster' &&
|
|
105
|
-
entry.renderableIndex === row.renderableIndex &&
|
|
106
|
-
entry.materialHandle === (material.materialHandle ?? -1),
|
|
107
|
-
)
|
|
108
|
-
: forwardProgramEntries.get(`${row.renderableIndex}:${material.materialHandle ?? -1}`);
|
|
116
|
+
pass === 'shadow' ? shadowProgramEntry : forwardProgramEntries.get(programKey);
|
|
109
117
|
const selectedArtifact =
|
|
110
118
|
artifact === undefined
|
|
111
119
|
? undefined
|
|
@@ -118,10 +118,18 @@ function hasMaterialResources(
|
|
|
118
118
|
// is a readiness requirement; this keeps numeric-only PBR on the same GPU
|
|
119
119
|
// lane while still rejecting an authored handle that failed to resolve.
|
|
120
120
|
return receipt.resourceSlots.every((slot) => {
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
|
|
121
|
+
// The renderer-owned Surface page is the one storage resource that is
|
|
122
|
+
// intentionally available to a scene-index draw. Its address is
|
|
123
|
+
// published in the Surface ABI; every other storage declaration still
|
|
124
|
+
// fails closed because MaterialSnapshot has no generic storage handle.
|
|
125
|
+
if (slot.kind === 'storage-buffer') {
|
|
126
|
+
return (
|
|
127
|
+
receipt.surface?.dynamicInput?.group === slot.group &&
|
|
128
|
+
receipt.surface.dynamicInput.binding === slot.binding &&
|
|
129
|
+
slot.group === 3 &&
|
|
130
|
+
slot.binding === 3
|
|
131
|
+
);
|
|
132
|
+
}
|
|
125
133
|
if (slot.kind === 'texture') {
|
|
126
134
|
if (!authoredTextures?.has(slot.parameter)) return true;
|
|
127
135
|
return (
|