@forgeax/engine-render 0.1.4 → 0.1.6
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 +130 -641
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +2 -0
- package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +2 -0
- package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +1 -0
- package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -1
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +6 -0
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -1
- package/dist/{gpu-driven/view-reference.d.ts → __tests__/gpu-driven-view-reference.d.ts} +4 -4
- package/dist/__tests__/gpu-driven-view-reference.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -1
- package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +2 -0
- package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +1 -0
- package/dist/__tests__/morph-feature-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-plan.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-plan.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ssao-config.unit.test.d.ts +2 -0
- package/dist/__tests__/ssao-config.unit.test.d.ts.map +1 -0
- package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +2 -0
- package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +1 -0
- package/dist/__tests__/standard-descriptors.test-d.d.ts +2 -0
- package/dist/__tests__/standard-descriptors.test-d.d.ts.map +1 -0
- package/dist/__tests__/standard-pipeline.dawn.test.d.ts +2 -0
- package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/standard-pipeline.integration.test.d.ts +2 -0
- package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +1 -0
- package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +2 -0
- package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +1 -0
- package/dist/{renderer/backend-selection.d.ts → assembly/backend-contract.d.ts} +15 -4
- package/dist/assembly/backend-contract.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +207 -0
- package/dist/assembly/factory.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +84 -0
- package/dist/assembly/host-contract.d.ts.map +1 -0
- package/dist/{renderer → assembly}/material/assembly.d.ts +0 -1
- package/dist/{renderer → assembly}/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-projection.d.ts +30 -0
- package/dist/assembly/material/pipeline-projection.d.ts.map +1 -0
- package/dist/authoring.d.ts +10 -11
- package/dist/authoring.d.ts.map +1 -1
- package/dist/authoring.mjs +25 -3
- package/dist/authoring.mjs.map +1 -1
- package/dist/chunk-CQXZC5XI.mjs +182 -0
- package/dist/chunk-CQXZC5XI.mjs.map +1 -0
- package/dist/chunk-QC4VW3XJ.mjs +79 -0
- package/dist/chunk-QC4VW3XJ.mjs.map +1 -0
- package/dist/chunk-SCRSAK5B.mjs +480 -0
- package/dist/chunk-SCRSAK5B.mjs.map +1 -0
- package/dist/components/__tests__/schema-contract.unit.test.d.ts +2 -0
- package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +1 -0
- package/dist/components/glyph-text.d.ts +1 -1
- package/dist/components/glyph-text.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +1 -1
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts +1 -1
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/mesh-filter.d.ts +7 -7
- package/dist/components/mesh-filter.d.ts.map +1 -1
- package/dist/components/scene-instance.d.ts +11 -11
- package/dist/components/skybox-background.d.ts +56 -0
- package/dist/components/skybox-background.d.ts.map +1 -0
- package/dist/components/skylight.d.ts +55 -0
- package/dist/components/skylight.d.ts.map +1 -0
- package/dist/components/sprite-animation.d.ts +2 -3
- package/dist/components/sprite-animation.d.ts.map +1 -1
- package/dist/components/sprite-instances.d.ts +1 -1
- package/dist/components/sprite-playback-mode.d.ts +6 -1
- package/dist/components/sprite-playback-mode.d.ts.map +1 -1
- package/dist/components/sprite-region-override.d.ts +2 -3
- package/dist/components/sprite-region-override.d.ts.map +1 -1
- package/dist/components/tile-layer.d.ts +5 -0
- package/dist/components/tile-layer.d.ts.map +1 -1
- package/dist/construct-renderer.d.ts +18 -1
- package/dist/construct-renderer.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +27008 -4
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/debug-draw-glue.d.ts +2 -53
- package/dist/debug-draw-glue.d.ts.map +1 -1
- package/dist/device/device-scope.d.ts +83 -0
- package/dist/device/device-scope.d.ts.map +1 -0
- package/dist/{gpu-resource-store.d.ts → device/gpu-residency.d.ts} +91 -48
- package/dist/device/gpu-residency.d.ts.map +1 -0
- package/dist/device/resource-types.d.ts +8 -0
- package/dist/device/resource-types.d.ts.map +1 -0
- package/dist/engine-metrics.d.ts +2 -2
- package/dist/engine-metrics.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +28 -1
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +249 -258
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/features/fullscreen.d.ts +19 -0
- package/dist/features/fullscreen.d.ts.map +1 -0
- package/dist/features/host.d.ts +32 -26
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/morph/morph-feature.d.ts +39 -5
- package/dist/features/morph/morph-feature.d.ts.map +1 -1
- package/dist/features/plan.d.ts +182 -0
- package/dist/features/plan.d.ts.map +1 -0
- package/dist/features/prepared-gpu-work.d.ts +21 -17
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics-store.d.ts +2 -1
- package/dist/features/prepared-graphics-store.d.ts.map +1 -1
- package/dist/features/prepared-graphics.d.ts +11 -21
- package/dist/features/prepared-graphics.d.ts.map +1 -1
- package/dist/features/render-graph-compute.d.ts +2 -2
- package/dist/features/render-graph-compute.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +4 -7
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +2 -2
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/render-graph-resources.d.ts +6 -6
- package/dist/features/render-graph-resources.d.ts.map +1 -1
- package/dist/features/targets.d.ts +5 -5
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +11 -190
- package/dist/features/types.d.ts.map +1 -1
- package/dist/features/vocabulary.d.ts +14 -0
- package/dist/features/vocabulary.d.ts.map +1 -0
- package/dist/fullscreen-post-process-pass.d.ts +4 -25
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/glyph-text-layout-system.d.ts +3 -2
- package/dist/glyph-text-layout-system.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +6 -75
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +13 -112
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/view-gpu.d.ts +10 -66
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-resource.d.ts +3 -3
- package/dist/gpu-scene-schema.d.ts +1 -94
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +7 -33
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +3 -53
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +74 -180
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +1 -1
- package/dist/index.d.ts +13 -43
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +165 -3
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +69 -0
- package/dist/inspection-types.d.ts.map +1 -0
- package/dist/instance-buffer-cache.d.ts +1 -4
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/internal.d.ts +1 -73
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +1 -43
- package/dist/internal.mjs.map +1 -1
- package/dist/lifecycle.d.ts +36 -2
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/materials.d.ts +0 -3
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +0 -1
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +75 -29
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts +5 -0
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts +31 -0
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -0
- package/dist/pipeline/standard-profile.d.ts +40 -0
- package/dist/pipeline/standard-profile.d.ts.map +1 -0
- package/dist/pipeline-builder.d.ts +3 -3
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec-types.d.ts +24 -0
- package/dist/pipeline-spec-types.d.ts.map +1 -0
- package/dist/pipeline-spec.d.ts +16 -155
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/plugin.d.ts +1 -14
- package/dist/plugin.d.ts.map +1 -1
- package/dist/post-process-errors.d.ts +18 -18
- package/dist/post-process-errors.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +2 -5
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +2 -0
- package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +7 -73
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +44 -44
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts +5 -38
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +64 -52
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +3 -2
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +5 -4
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +90 -59
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +28 -3
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +1 -1
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +276 -3
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +235 -0
- package/dist/record/render-context.d.ts.map +1 -0
- package/dist/record/shadow-pass.d.ts +15 -88
- 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 +29 -7
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +3 -3
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/render-contract.d.ts +416 -0
- package/dist/render-contract.d.ts.map +1 -0
- package/dist/render-data.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +14 -362
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +25 -64
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +107 -338
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +21 -713
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene-types.d.ts +58 -0
- package/dist/scene/render-scene-types.d.ts.map +1 -0
- package/dist/scene/render-scene.d.ts +105 -0
- package/dist/scene/render-scene.d.ts.map +1 -0
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts +2 -5
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +22 -3
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/systems/skin-palette-allocator.d.ts +2 -4
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/systems/skin-palette-types.d.ts +14 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -0
- package/dist/systems/transparent-sort-config.d.ts +23 -2
- package/dist/systems/transparent-sort-config.d.ts.map +1 -1
- package/dist/tilemap-chunk-extract-system.d.ts +4 -3
- package/dist/tilemap-chunk-extract-system.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +2 -4
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +3 -3
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/package.json +23 -23
- package/src/__tests__/backend-selection-rhi-capture.test-d.ts +1 -1
- package/src/__tests__/callback-inference.test-d.ts +6 -3
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -4
- package/src/__tests__/construct-renderer-identity.unit.test.ts +15 -2
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +151 -0
- package/src/__tests__/device-scope-stale-matrix.unit.test.ts +42 -0
- package/src/__tests__/direct-extract-consumer-contract.test-d.ts +8 -19
- package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -13
- package/src/__tests__/factory-contract.integration.test.ts +158 -209
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +1 -4
- package/src/__tests__/frame-observation.contract.test.ts +17 -8
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
- package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +6 -11
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +9 -16
- package/src/__tests__/gpu-driven-production.integration.test.ts +32 -205
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +4 -7
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +87 -8
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +170 -8
- package/src/{gpu-driven/view-reference.ts → __tests__/gpu-driven-view-reference.ts} +4 -3
- package/src/__tests__/gpu-driven-view.browser.test.ts +12 -1
- package/src/__tests__/gpu-driven-view.dawn.test.ts +12 -1
- package/src/__tests__/gpu-driven-view.unit.test.ts +11 -267
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +3 -3
- package/src/__tests__/gpu-scene-render-graph-gpu.ts +2 -3
- package/src/__tests__/gpu-scene.dawn.test.ts +2 -6
- package/src/__tests__/gpu-scene.unit.test.ts +10 -24
- package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
- package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +34 -66
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -5
- package/src/__tests__/light-buffer-layout.unit.test.ts +4 -49
- package/src/__tests__/material-cooked-projection.unit.test.ts +2 -51
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +10 -15
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +4 -23
- package/src/__tests__/material-stride-surface.unit.test.ts +2 -2
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +7 -8
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +29 -38
- package/src/__tests__/morph-feature-gpu-work.integration.test.ts +45 -43
- package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
- package/src/__tests__/morph-visual-evidence.integration.test.ts +47 -33
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +11 -6
- package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -13
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +6 -81
- package/src/__tests__/prepared-graphics-generation.unit.test.ts +3 -17
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +6 -74
- package/src/__tests__/prepared-graphics-resolver.unit.test.ts +1 -3
- package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +2 -2
- package/src/__tests__/profiler-default-off.test.ts +1 -1
- package/src/__tests__/profiler-phase-catalog.test.ts +2 -2
- package/src/__tests__/profiler-phase-integration.test.ts +5 -13
- package/src/__tests__/profiler-phase-token.test.ts +3 -8
- package/src/__tests__/public-surface.test-d.ts +65 -3
- package/src/__tests__/recover-error-policy-owner.unit.test.ts +1 -21
- package/src/__tests__/render-error-code-owner.test-d.ts +18 -23
- package/src/__tests__/render-error-detail-ssot.test-d.ts +0 -95
- package/src/__tests__/render-error-exhaustive.test-d.ts +8 -1
- package/src/__tests__/render-feature-assembly.test-d.ts +8 -16
- package/src/__tests__/render-feature-context.test-d.ts +16 -40
- package/src/__tests__/render-feature-contract.test-d.ts +9 -18
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +6 -8
- package/src/__tests__/render-feature-docs.unit.test.ts +8 -7
- package/src/__tests__/render-feature-gpu-work.integration.test.ts +14 -75
- package/src/__tests__/render-feature-plan.test-d.ts +161 -0
- package/src/__tests__/render-feature-plan.unit.test.ts +170 -0
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +8 -19
- package/src/__tests__/render-feature-prepared-errors.test-d.ts +3 -6
- package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +10 -71
- package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +11 -61
- package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +20 -43
- package/src/__tests__/render-feature-prepared-graphics.test-d.ts +56 -78
- package/src/__tests__/render-feature-public-surface.test-d.ts +6 -24
- package/src/__tests__/render-feature-retry.unit.test.ts +7 -48
- package/src/__tests__/render-feature-scheduling.unit.test.ts +15 -27
- package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +0 -9
- package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +19 -109
- package/src/__tests__/render-feature-visibility-context.test-d.ts +1 -6
- package/src/__tests__/render-feature-visibility-context.unit.test.ts +1 -2
- package/src/__tests__/render-feature-zero-work.unit.test.ts +14 -20
- package/src/__tests__/render-scene-projection.unit.test.ts +73 -111
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +44 -95
- package/src/__tests__/renderer-lifecycle.integration.test.ts +49 -1
- package/src/__tests__/shader-stage-surface.unit.test.ts +14 -9
- package/src/__tests__/ssao-config.unit.test.ts +36 -0
- package/src/__tests__/ssao-kernel-surface.unit.test.ts +4 -5
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +28 -0
- package/src/__tests__/standard-descriptors.test-d.ts +22 -0
- package/src/__tests__/standard-pipeline.dawn.test.ts +61 -0
- package/src/__tests__/standard-pipeline.integration.test.ts +124 -0
- package/src/__tests__/standard-profile-oracle.unit.test.ts +62 -0
- package/src/__tests__/surface-configuration.unit.test.ts +1 -2
- package/src/__tests__/texture-usage-surface.unit.test.ts +3 -6
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +40 -206
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +1 -11
- package/src/__tests__/urp-pipeline.unit.test.ts +2 -2
- package/src/__tests__/vertex-color-pipeline.unit.test.ts +10 -2
- package/src/__tests__/vertex-layout-consumer.unit.test.ts +1 -1
- package/src/__tests__/visibility-diagnostics.integration.test.ts +7 -11
- package/src/__tests__/visibility-extract.integration.test.ts +20 -11
- package/src/__tests__/visibility-extract.perf.test.ts +66 -32
- package/src/__tests__/visibility-feature-dedup.integration.test.ts +2 -4
- package/src/__tests__/visibility-hidden-report.unit.test.ts +1 -2
- package/src/__tests__/visibility-instances.integration.test.ts +7 -11
- package/src/__tests__/visibility-multi-world.integration.test.ts +38 -6
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +18 -41
- package/src/__tests__/visibility-public-surface.test-d.ts +10 -9
- package/src/__tests__/visibility-resolver.unit.test.ts +2 -1
- package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
- package/src/__tests__/visibility-snapshot-contract.unit.test.ts +2 -1
- package/src/__tests__/vocabulary.unit.test.ts +1 -1
- package/src/assembly/backend-contract.ts +57 -0
- package/src/{renderer/renderer-factory.ts → assembly/factory.ts} +1663 -2690
- package/src/assembly/host-contract.ts +101 -0
- package/src/{renderer → assembly}/material/assembly.ts +0 -2
- package/src/assembly/material/pipeline-projection.ts +63 -0
- package/src/authoring.ts +14 -22
- package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
- package/src/components/glyph-text.ts +3 -2
- package/src/components/index.ts +7 -9
- package/src/components/instances.ts +4 -5
- package/src/components/light-helpers.ts +1 -1
- package/src/components/mesh-filter.ts +11 -10
- package/src/components/post-process-params.ts +3 -3
- package/src/components/scene-instance.ts +12 -12
- package/src/components/skybox-background.ts +103 -0
- package/src/components/{environment.ts → skylight.ts} +2 -110
- package/src/components/sprite-animation.ts +3 -4
- package/src/components/sprite-instances.ts +2 -2
- package/src/components/sprite-playback-mode.ts +7 -1
- package/src/components/sprite-region-override.ts +2 -3
- package/src/components/tile-layer.ts +8 -2
- package/src/construct-renderer.ts +67 -4
- package/src/debug-draw-glue.ts +8 -129
- package/src/device/device-scope.ts +306 -0
- package/src/{gpu-resource-store.ts → device/gpu-residency.ts} +540 -639
- package/src/device/resource-types.ts +20 -0
- package/src/engine-metrics.ts +12 -19
- package/src/errors/recover.ts +45 -3
- package/src/errors/render.ts +357 -460
- package/src/features/fullscreen.ts +46 -0
- package/src/features/host.ts +575 -309
- package/src/features/morph/morph-feature.ts +195 -105
- package/src/features/plan.ts +447 -0
- package/src/features/prepared-gpu-work.ts +72 -15
- package/src/features/prepared-graphics-store.ts +20 -6
- package/src/features/prepared-graphics.ts +12 -71
- package/src/features/render-graph-compute.ts +14 -5
- package/src/features/render-graph-contribution.ts +43 -63
- package/src/features/render-graph-raster.ts +11 -6
- package/src/features/render-graph-resources.ts +25 -23
- package/src/features/targets.ts +8 -21
- package/src/features/types.ts +39 -227
- package/src/features/vocabulary.ts +24 -0
- package/src/fullscreen-post-process-pass.ts +14 -57
- package/src/glyph-text-layout-system.ts +70 -96
- package/src/gpu-driven/batch-topology.ts +24 -202
- package/src/gpu-driven/production-raster.ts +93 -1108
- package/src/gpu-driven/view-gpu.ts +46 -192
- package/src/gpu-resource.ts +4 -4
- package/src/gpu-scene-schema.ts +11 -99
- package/src/gpu-scene.ts +231 -364
- package/src/hdrp-buffers.ts +12 -221
- package/src/ibl/IblPipelineCache.ts +471 -711
- package/src/ibl/skylight-bind-group.ts +4 -4
- package/src/index.ts +58 -217
- package/src/inspection-types.ts +76 -0
- package/src/instance-buffer-cache.ts +1 -29
- package/src/internal.ts +6 -85
- package/src/lifecycle.ts +64 -19
- package/src/materials.ts +7 -29
- package/src/mesh-material-bindings.ts +0 -1
- package/src/pbr-pipeline.ts +434 -53
- package/src/{urp-pipeline.ts → pipeline/standard-forward-lane.ts} +38 -149
- package/src/{hdrp-pipeline.ts → pipeline/standard-pipeline.ts} +221 -191
- package/src/pipeline/standard-profile.ts +65 -0
- package/src/pipeline-builder.ts +60 -64
- package/src/pipeline-spec-types.ts +28 -0
- package/src/pipeline-spec.ts +72 -609
- package/src/plugin.ts +3 -75
- package/src/post-process-errors.ts +31 -33
- package/src/prepare/prepared-graphics-resolver.ts +5 -4
- package/src/record/__tests__/material-slot-plan.unit.test.ts +1 -33
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
- package/src/record/__tests__/video-texture-view.unit.test.ts +1 -1
- package/src/record/frame-lighting.ts +74 -195
- package/src/record/frame-snapshot.ts +45 -60
- package/src/record/frame-targets.ts +8 -243
- package/src/record/frame.ts +509 -796
- package/src/record/helpers.ts +6 -11
- package/src/record/main-pass-geometry.ts +106 -147
- package/src/record/main-pass-material.ts +517 -190
- package/src/record/main-pass-sprite-draws.ts +198 -117
- package/src/record/main-pass.ts +162 -143
- package/src/record/mesh-ssbo.ts +517 -38
- package/src/record/render-context.ts +364 -0
- package/src/record/shadow-pass.ts +138 -1838
- package/src/record/skybox-post-pass.ts +12 -14
- package/src/record/typed-frame-graph.ts +215 -254
- package/src/record/view-ubo.ts +6 -37
- package/src/render-contract.ts +571 -0
- package/src/render-data.ts +3 -3
- package/src/render-graph-primitives.ts +76 -851
- package/src/render-pipeline.ts +104 -188
- package/src/render-system-extract.ts +1048 -1729
- package/src/render-system.ts +330 -1957
- package/src/scene/render-scene-types.ts +64 -0
- package/src/scene/render-scene.ts +1032 -0
- package/src/scene-instances/post-spawn-resolve-joints.ts +4 -7
- package/src/ssao-buffers.ts +167 -8
- package/src/systems/skin-palette-allocator.ts +21 -64
- package/src/systems/skin-palette-types.ts +14 -0
- package/src/systems/transparent-sort-config.ts +25 -3
- package/src/tilemap-chunk-extract-system.ts +53 -70
- package/src/typed-render-graph-primitives.ts +35 -24
- package/src/typed-shadow-passes.ts +26 -56
- package/dist/__tests__/analytic-sky-contract.test.d.ts +0 -2
- package/dist/__tests__/analytic-sky-contract.test.d.ts.map +0 -1
- package/dist/__tests__/analytic-sky-falsify.test.d.ts +0 -2
- package/dist/__tests__/analytic-sky-falsify.test.d.ts.map +0 -1
- package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts +0 -2
- package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts.map +0 -1
- package/dist/__tests__/backend-selection.integration.test.d.ts +0 -2
- package/dist/__tests__/backend-selection.integration.test.d.ts.map +0 -1
- package/dist/__tests__/camera-temporal.test-d.d.ts +0 -2
- package/dist/__tests__/camera-temporal.test-d.d.ts.map +0 -1
- package/dist/__tests__/camera-temporal.test.d.ts +0 -2
- package/dist/__tests__/camera-temporal.test.d.ts.map +0 -1
- package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts +0 -2
- package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts.map +0 -1
- package/dist/__tests__/environment-inspection.test.d.ts +0 -2
- package/dist/__tests__/environment-inspection.test.d.ts.map +0 -1
- package/dist/__tests__/fog-ai-user.fixture.d.ts +0 -2
- package/dist/__tests__/fog-ai-user.fixture.d.ts.map +0 -1
- package/dist/__tests__/fog-custom-render-feature.fixture.d.ts +0 -16
- package/dist/__tests__/fog-custom-render-feature.fixture.d.ts.map +0 -1
- package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-inspection.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-inspection.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-owner-state.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-owner-state.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-public-surface.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-public-surface.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-ray-contract.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-ray-contract.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-source-absence.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-source-absence.integration.test.d.ts.map +0 -1
- package/dist/__tests__/fog-temporal.integration.test.d.ts +0 -2
- package/dist/__tests__/fog-temporal.integration.test.d.ts.map +0 -1
- package/dist/__tests__/frame-chain.unit.test.d.ts +0 -2
- package/dist/__tests__/frame-chain.unit.test.d.ts.map +0 -1
- package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts +0 -2
- package/dist/__tests__/gpu-scene-field-type-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/hdrp-pipeline.unit.test.d.ts +0 -2
- package/dist/__tests__/hdrp-pipeline.unit.test.d.ts.map +0 -1
- package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts +0 -2
- package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts.map +0 -1
- package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts +0 -2
- package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts.map +0 -1
- package/dist/__tests__/material-derived-payload.integration.test.d.ts +0 -2
- package/dist/__tests__/material-derived-payload.integration.test.d.ts.map +0 -1
- package/dist/__tests__/materials.unit.test.d.ts +0 -2
- package/dist/__tests__/materials.unit.test.d.ts.map +0 -1
- package/dist/__tests__/param-schema-projection-census.unit.test.d.ts +0 -2
- package/dist/__tests__/param-schema-projection-census.unit.test.d.ts.map +0 -1
- package/dist/__tests__/persistent-render-scene.unit.test.d.ts +0 -2
- package/dist/__tests__/persistent-render-scene.unit.test.d.ts.map +0 -1
- package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts +0 -2
- package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts.map +0 -1
- package/dist/__tests__/pipeline-pass-trace.test.d.ts +0 -2
- package/dist/__tests__/pipeline-pass-trace.test.d.ts.map +0 -1
- package/dist/__tests__/pipeline-stage-owner.test-d.d.ts +0 -2
- package/dist/__tests__/pipeline-stage-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/plugin.test.d.ts +0 -2
- package/dist/__tests__/plugin.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.d.ts.map +0 -1
- package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts +0 -2
- package/dist/__tests__/prepared-graphics-resolver-recording.unit.test.d.ts.map +0 -1
- package/dist/__tests__/public-pipeline-id.test-d.d.ts +0 -2
- package/dist/__tests__/public-pipeline-id.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-dispatch-membership.unit.test.d.ts +0 -2
- package/dist/__tests__/render-dispatch-membership.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-construction.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-construction.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-error-code-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts +0 -2
- package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/render-feature-graph.integration.test.d.ts +0 -2
- package/dist/__tests__/render-feature-graph.integration.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-order.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-order.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.d.ts.map +0 -1
- package/dist/__tests__/render-feature-staging.unit.test.d.ts +0 -2
- package/dist/__tests__/render-feature-staging.unit.test.d.ts.map +0 -1
- package/dist/__tests__/renderer-render-scene-public.test-d.d.ts +0 -2
- package/dist/__tests__/renderer-render-scene-public.test-d.d.ts.map +0 -1
- package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts +0 -2
- package/dist/__tests__/scene-temporal-coverage.unit.test.d.ts.map +0 -1
- package/dist/__tests__/sun-snapshot-consumers.test.d.ts +0 -2
- package/dist/__tests__/sun-snapshot-consumers.test.d.ts.map +0 -1
- package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts +0 -2
- package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts.map +0 -1
- package/dist/__tests__/taa-history-store.unit.test.d.ts +0 -2
- package/dist/__tests__/taa-history-store.unit.test.d.ts.map +0 -1
- package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts +0 -2
- package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts.map +0 -1
- package/dist/__tests__/temporal-inspection.unit.test.d.ts +0 -2
- package/dist/__tests__/temporal-inspection.unit.test.d.ts.map +0 -1
- package/dist/assets/__tests__/asset-decoders.unit.test.d.ts +0 -2
- package/dist/assets/__tests__/asset-decoders.unit.test.d.ts.map +0 -1
- package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts +0 -2
- package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts.map +0 -1
- package/dist/assets/__tests__/render-asset-port.unit.test.d.ts +0 -2
- package/dist/assets/__tests__/render-asset-port.unit.test.d.ts.map +0 -1
- package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts +0 -2
- package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts.map +0 -1
- package/dist/chunk-DJIMFYX6.mjs +0 -1439
- package/dist/chunk-DJIMFYX6.mjs.map +0 -1
- package/dist/chunk-F2SIOCRM.mjs +0 -7423
- package/dist/chunk-F2SIOCRM.mjs.map +0 -1
- package/dist/chunk-JMSB7AR4.mjs +0 -3
- package/dist/chunk-JMSB7AR4.mjs.map +0 -1
- package/dist/chunk-KHI6K4C6.mjs +0 -659
- package/dist/chunk-KHI6K4C6.mjs.map +0 -1
- package/dist/chunk-PORZOL2V.mjs +0 -569
- package/dist/chunk-PORZOL2V.mjs.map +0 -1
- package/dist/chunk-UOJGMDGP.mjs +0 -29913
- package/dist/chunk-UOJGMDGP.mjs.map +0 -1
- package/dist/components/__tests__/atmosphere-red.test.d.ts +0 -2
- package/dist/components/__tests__/atmosphere-red.test.d.ts.map +0 -1
- package/dist/components/__tests__/atmosphere.test.d.ts +0 -2
- package/dist/components/__tests__/atmosphere.test.d.ts.map +0 -1
- package/dist/components/__tests__/fog.test-d.d.ts +0 -2
- package/dist/components/__tests__/fog.test-d.d.ts.map +0 -1
- package/dist/components/__tests__/fog.test.d.ts +0 -2
- package/dist/components/__tests__/fog.test.d.ts.map +0 -1
- package/dist/components/atmosphere.d.ts +0 -18
- package/dist/components/atmosphere.d.ts.map +0 -1
- package/dist/components/environment.d.ts +0 -115
- package/dist/components/environment.d.ts.map +0 -1
- package/dist/deferred-lighting.d.ts +0 -13
- package/dist/deferred-lighting.d.ts.map +0 -1
- package/dist/dynamic-texture-store.d.ts +0 -42
- package/dist/dynamic-texture-store.d.ts.map +0 -1
- package/dist/environment/__tests__/failure-injection.test.d.ts +0 -2
- package/dist/environment/__tests__/failure-injection.test.d.ts.map +0 -1
- package/dist/environment/__tests__/generation-red.test.d.ts +0 -2
- package/dist/environment/__tests__/generation-red.test.d.ts.map +0 -1
- package/dist/environment/__tests__/generation.test.d.ts +0 -2
- package/dist/environment/__tests__/generation.test.d.ts.map +0 -1
- package/dist/environment/__tests__/graph-transaction.test.d.ts +0 -2
- package/dist/environment/__tests__/graph-transaction.test.d.ts.map +0 -1
- package/dist/environment/__tests__/inspection-red.test.d.ts +0 -2
- package/dist/environment/__tests__/inspection-red.test.d.ts.map +0 -1
- package/dist/environment/__tests__/lifecycle-evidence.test.d.ts +0 -2
- package/dist/environment/__tests__/lifecycle-evidence.test.d.ts.map +0 -1
- package/dist/environment/__tests__/pipeline-topology.test.d.ts +0 -2
- package/dist/environment/__tests__/pipeline-topology.test.d.ts.map +0 -1
- package/dist/environment/__tests__/readiness.test.d.ts +0 -2
- package/dist/environment/__tests__/readiness.test.d.ts.map +0 -1
- package/dist/environment/__tests__/recovery.test.d.ts +0 -2
- package/dist/environment/__tests__/recovery.test.d.ts.map +0 -1
- package/dist/environment/__tests__/resize-dispose.test.d.ts +0 -2
- package/dist/environment/__tests__/resize-dispose.test.d.ts.map +0 -1
- package/dist/environment/__tests__/signature-red.test.d.ts +0 -2
- package/dist/environment/__tests__/signature-red.test.d.ts.map +0 -1
- package/dist/environment/__tests__/signature.test.d.ts +0 -2
- package/dist/environment/__tests__/signature.test.d.ts.map +0 -1
- package/dist/environment/descriptors.d.ts +0 -2
- package/dist/environment/descriptors.d.ts.map +0 -1
- package/dist/environment/extracted-environment.d.ts +0 -53
- package/dist/environment/extracted-environment.d.ts.map +0 -1
- package/dist/environment/generation.d.ts +0 -62
- package/dist/environment/generation.d.ts.map +0 -1
- package/dist/environment/gpu-bundle.d.ts +0 -23
- package/dist/environment/gpu-bundle.d.ts.map +0 -1
- package/dist/environment/graph.d.ts +0 -108
- package/dist/environment/graph.d.ts.map +0 -1
- package/dist/environment/inspection.d.ts +0 -48
- package/dist/environment/inspection.d.ts.map +0 -1
- package/dist/environment/lifecycle.d.ts +0 -22
- package/dist/environment/lifecycle.d.ts.map +0 -1
- package/dist/environment/readiness.d.ts +0 -29
- package/dist/environment/readiness.d.ts.map +0 -1
- package/dist/environment/signature.d.ts +0 -70
- package/dist/environment/signature.d.ts.map +0 -1
- package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts +0 -2
- package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts.map +0 -1
- package/dist/extract/__tests__/environment-source.test.d.ts +0 -2
- package/dist/extract/__tests__/environment-source.test.d.ts.map +0 -1
- package/dist/extract/__tests__/schema-readers.unit.test.d.ts +0 -2
- package/dist/extract/__tests__/schema-readers.unit.test.d.ts.map +0 -1
- package/dist/extract/directional-csm.d.ts +0 -129
- package/dist/extract/directional-csm.d.ts.map +0 -1
- package/dist/extract/index.d.ts +0 -5
- package/dist/extract/index.d.ts.map +0 -1
- package/dist/extract/material-interface.d.ts +0 -56
- package/dist/extract/material-interface.d.ts.map +0 -1
- package/dist/extract/schema-readers.d.ts +0 -20
- package/dist/extract/schema-readers.d.ts.map +0 -1
- package/dist/features/graph-contribution.d.ts +0 -64
- package/dist/features/graph-contribution.d.ts.map +0 -1
- package/dist/features/index.d.ts +0 -21
- package/dist/features/index.d.ts.map +0 -1
- package/dist/features/morph/index.d.ts +0 -3
- package/dist/features/morph/index.d.ts.map +0 -1
- package/dist/features/morph/morph-bounds.d.ts +0 -42
- package/dist/features/morph/morph-bounds.d.ts.map +0 -1
- package/dist/features/scene-temporal.d.ts +0 -45
- package/dist/features/scene-temporal.d.ts.map +0 -1
- package/dist/features/taa-resolve.d.ts +0 -21
- package/dist/features/taa-resolve.d.ts.map +0 -1
- package/dist/frame-chain.d.ts +0 -14
- package/dist/frame-chain.d.ts.map +0 -1
- package/dist/gpu-driven/view-reference.d.ts.map +0 -1
- package/dist/gpu-resource-store.d.ts.map +0 -1
- package/dist/hdrp-cluster-membership.d.ts +0 -2
- package/dist/hdrp-cluster-membership.d.ts.map +0 -1
- package/dist/hdrp-pipeline.d.ts +0 -36
- package/dist/hdrp-pipeline.d.ts.map +0 -1
- package/dist/ibl/cubemap-projection.d.ts +0 -23
- package/dist/ibl/cubemap-projection.d.ts.map +0 -1
- package/dist/ibl/face-uniforms.d.ts +0 -65
- package/dist/ibl/face-uniforms.d.ts.map +0 -1
- package/dist/mesh-update-errors.d.ts +0 -71
- package/dist/mesh-update-errors.d.ts.map +0 -1
- package/dist/mipmap-generator.d.ts +0 -39
- package/dist/mipmap-generator.d.ts.map +0 -1
- package/dist/param-schema-projection-census.d.ts +0 -18
- package/dist/param-schema-projection-census.d.ts.map +0 -1
- package/dist/persistent-render-scene.d.ts +0 -158
- package/dist/persistent-render-scene.d.ts.map +0 -1
- package/dist/pipeline/index.d.ts +0 -11
- package/dist/pipeline/index.d.ts.map +0 -1
- package/dist/pipeline-errors.d.ts +0 -110
- package/dist/pipeline-errors.d.ts.map +0 -1
- package/dist/prepare/__tests__/schema-readers.unit.test.d.ts +0 -2
- package/dist/prepare/__tests__/schema-readers.unit.test.d.ts.map +0 -1
- package/dist/prepare/index.d.ts +0 -4
- package/dist/prepare/index.d.ts.map +0 -1
- package/dist/prepare/schema-readers.d.ts +0 -11
- package/dist/prepare/schema-readers.d.ts.map +0 -1
- package/dist/record/__tests__/environment-record.test.d.ts +0 -2
- package/dist/record/__tests__/environment-record.test.d.ts.map +0 -1
- package/dist/record/__tests__/frame-targets.unit.test.d.ts +0 -2
- package/dist/record/__tests__/frame-targets.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/membership-timing.unit.test.d.ts +0 -2
- package/dist/record/__tests__/membership-timing.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/render-submission.integration.test.d.ts +0 -2
- package/dist/record/__tests__/render-submission.integration.test.d.ts.map +0 -1
- package/dist/record/__tests__/render-submission.perf.test.d.ts +0 -2
- package/dist/record/__tests__/render-submission.perf.test.d.ts.map +0 -1
- package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts +0 -2
- package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts.map +0 -1
- package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts +0 -2
- package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts.map +0 -1
- package/dist/record/frame-observation.d.ts +0 -38
- package/dist/record/frame-observation.d.ts.map +0 -1
- package/dist/record/index.d.ts +0 -15
- package/dist/record/index.d.ts.map +0 -1
- package/dist/record/main-pass-skin.d.ts +0 -46
- package/dist/record/main-pass-skin.d.ts.map +0 -1
- package/dist/record/main-pass-sprite.d.ts +0 -69
- package/dist/record/main-pass-sprite.d.ts.map +0 -1
- package/dist/record/material-payload.d.ts +0 -43
- package/dist/record/material-payload.d.ts.map +0 -1
- package/dist/record/material-slot-plan.d.ts +0 -26
- package/dist/record/material-slot-plan.d.ts.map +0 -1
- package/dist/record/membership-timing.d.ts +0 -232
- package/dist/record/membership-timing.d.ts.map +0 -1
- package/dist/record/shadow-caster-uniform.d.ts +0 -8
- package/dist/record/shadow-caster-uniform.d.ts.map +0 -1
- package/dist/record/shadow-submit-mode.d.ts +0 -66
- package/dist/record/shadow-submit-mode.d.ts.map +0 -1
- package/dist/render-dispatch-membership.d.ts +0 -47
- package/dist/render-dispatch-membership.d.ts.map +0 -1
- package/dist/render-pipeline-context.d.ts +0 -289
- package/dist/render-pipeline-context.d.ts.map +0 -1
- package/dist/render-pipeline-target.d.ts +0 -16
- package/dist/render-pipeline-target.d.ts.map +0 -1
- package/dist/render-scene-projection.d.ts +0 -174
- package/dist/render-scene-projection.d.ts.map +0 -1
- package/dist/render-system-fold.d.ts +0 -266
- package/dist/render-system-fold.d.ts.map +0 -1
- package/dist/renderer/asset-service.d.ts +0 -10
- package/dist/renderer/asset-service.d.ts.map +0 -1
- package/dist/renderer/backend-selection.d.ts.map +0 -1
- package/dist/renderer/environment-classify.d.ts +0 -6
- package/dist/renderer/environment-classify.d.ts.map +0 -1
- package/dist/renderer/environment-error.d.ts +0 -13
- package/dist/renderer/environment-error.d.ts.map +0 -1
- package/dist/renderer/material/pipeline-projection.d.ts +0 -91
- package/dist/renderer/material/pipeline-projection.d.ts.map +0 -1
- package/dist/renderer/renderer-factory.d.ts +0 -289
- package/dist/renderer/renderer-factory.d.ts.map +0 -1
- package/dist/renderer.d.ts +0 -771
- package/dist/renderer.d.ts.map +0 -1
- package/dist/scene-utils/collect-subtree.d.ts +0 -11
- package/dist/scene-utils/collect-subtree.d.ts.map +0 -1
- package/dist/ssao-data.d.ts +0 -34
- package/dist/ssao-data.d.ts.map +0 -1
- package/dist/surface-format.d.ts +0 -10
- package/dist/surface-format.d.ts.map +0 -1
- package/dist/taa-history-store.d.ts +0 -88
- package/dist/taa-history-store.d.ts.map +0 -1
- package/dist/temporal-coverage.d.ts +0 -35
- package/dist/temporal-coverage.d.ts.map +0 -1
- package/dist/temporal-frame-transaction.d.ts +0 -92
- package/dist/temporal-frame-transaction.d.ts.map +0 -1
- package/dist/temporal-inspection.d.ts +0 -57
- package/dist/temporal-inspection.d.ts.map +0 -1
- package/dist/temporal-view.d.ts +0 -43
- package/dist/temporal-view.d.ts.map +0 -1
- package/dist/tilemap/resolve-tileset-runtime.d.ts +0 -23
- package/dist/tilemap/resolve-tileset-runtime.d.ts.map +0 -1
- package/dist/urp-pipeline.d.ts +0 -4
- package/dist/urp-pipeline.d.ts.map +0 -1
- package/src/__tests__/analytic-sky-contract.test.ts +0 -27
- package/src/__tests__/analytic-sky-falsify-carriers.mjs +0 -43
- package/src/__tests__/analytic-sky-falsify.test.ts +0 -94
- package/src/__tests__/assets-runtime-handoff.integration.test.ts +0 -36
- package/src/__tests__/backend-selection.integration.test.ts +0 -11
- package/src/__tests__/camera-temporal.test-d.ts +0 -8
- package/src/__tests__/camera-temporal.test.ts +0 -188
- package/src/__tests__/directional-shadow-probe-atlas-layout.unit.test.ts +0 -18
- package/src/__tests__/environment-inspection.test.ts +0 -45
- package/src/__tests__/fog-ai-user.fixture.ts +0 -350
- package/src/__tests__/fog-custom-render-feature.fixture.ts +0 -33
- package/src/__tests__/fog-custom-render-feature.integration.test.ts +0 -76
- package/src/__tests__/fog-inspection.integration.test.ts +0 -127
- package/src/__tests__/fog-owner-state.integration.test.ts +0 -112
- package/src/__tests__/fog-pipeline-topology.integration.test.ts +0 -93
- package/src/__tests__/fog-public-surface.integration.test.ts +0 -60
- package/src/__tests__/fog-ray-contract.integration.test.ts +0 -73
- package/src/__tests__/fog-source-absence.integration.test.ts +0 -51
- package/src/__tests__/fog-temporal.integration.test.ts +0 -115
- package/src/__tests__/frame-chain.unit.test.ts +0 -26
- package/src/__tests__/gpu-scene-field-type-owner.test-d.ts +0 -27
- package/src/__tests__/hdrp-pipeline.unit.test.ts +0 -100
- package/src/__tests__/ibl/ibl-fallback.unit.test.ts +0 -23
- package/src/__tests__/material-derived-error-stop-draw.integration.test.ts +0 -69
- package/src/__tests__/material-derived-payload.integration.test.ts +0 -164
- package/src/__tests__/materials.unit.test.ts +0 -25
- package/src/__tests__/param-schema-projection-census.unit.test.ts +0 -40
- package/src/__tests__/persistent-render-scene.unit.test.ts +0 -1311
- package/src/__tests__/pipeline-error-policy-owner.unit.test.ts +0 -167
- package/src/__tests__/pipeline-pass-trace.test.ts +0 -92
- package/src/__tests__/pipeline-stage-owner.test-d.ts +0 -13
- package/src/__tests__/plugin.test.ts +0 -25
- package/src/__tests__/prepared-graphics-backend-matrix.unit.test.ts +0 -129
- package/src/__tests__/prepared-graphics-resolver-recording.unit.test.ts +0 -180
- package/src/__tests__/public-pipeline-id.test-d.ts +0 -6
- package/src/__tests__/render-dispatch-membership.unit.test.ts +0 -117
- package/src/__tests__/render-feature-construction.unit.test.ts +0 -124
- package/src/__tests__/render-feature-error-code-owner.test-d.ts +0 -27
- package/src/__tests__/render-feature-gpu-buffer-usage-owner.test-d.ts +0 -46
- package/src/__tests__/render-feature-graph.integration.test.ts +0 -205
- package/src/__tests__/render-feature-graphics-staging.unit.test.ts +0 -200
- package/src/__tests__/render-feature-order.unit.test.ts +0 -66
- package/src/__tests__/render-feature-prepared-graphics-recording.unit.test.ts +0 -107
- package/src/__tests__/render-feature-staging.unit.test.ts +0 -94
- package/src/__tests__/renderer-render-scene-public.test-d.ts +0 -27
- package/src/__tests__/scene-temporal-coverage.unit.test.ts +0 -259
- package/src/__tests__/sun-snapshot-consumers.test.ts +0 -35
- package/src/__tests__/surface-backend-kind-owner.test-d.ts +0 -42
- package/src/__tests__/taa-history-store.unit.test.ts +0 -196
- package/src/__tests__/temporal-frame-transaction.integration.test.ts +0 -537
- package/src/__tests__/temporal-inspection.unit.test.ts +0 -138
- package/src/assets/__tests__/asset-decoders.unit.test.ts +0 -92
- package/src/assets/__tests__/mipmap-generator.unit.test.ts +0 -52
- package/src/assets/__tests__/render-asset-port.unit.test.ts +0 -54
- package/src/assets/__tests__/resolve-render-asset.unit.test.ts +0 -47
- package/src/components/__tests__/atmosphere-red.test.ts +0 -51
- package/src/components/__tests__/atmosphere.test.ts +0 -79
- package/src/components/__tests__/fog.test-d.ts +0 -49
- package/src/components/__tests__/fog.test.ts +0 -60
- package/src/components/atmosphere.ts +0 -64
- package/src/deferred-lighting.ts +0 -92
- package/src/dynamic-texture-store.ts +0 -111
- package/src/environment/README.md +0 -76
- package/src/environment/__tests__/failure-injection.test.ts +0 -50
- package/src/environment/__tests__/generation-red.test.ts +0 -64
- package/src/environment/__tests__/generation.test.ts +0 -37
- package/src/environment/__tests__/graph-transaction.test.ts +0 -85
- package/src/environment/__tests__/inspection-red.test.ts +0 -53
- package/src/environment/__tests__/lifecycle-evidence.test.ts +0 -40
- package/src/environment/__tests__/pipeline-topology.test.ts +0 -33
- package/src/environment/__tests__/readiness.test.ts +0 -42
- package/src/environment/__tests__/recovery.test.ts +0 -62
- package/src/environment/__tests__/resize-dispose.test.ts +0 -30
- package/src/environment/__tests__/signature-red.test.ts +0 -45
- package/src/environment/__tests__/signature.test.ts +0 -60
- package/src/environment/descriptors.ts +0 -7
- package/src/environment/extracted-environment.ts +0 -239
- package/src/environment/generation.ts +0 -158
- package/src/environment/gpu-bundle.ts +0 -144
- package/src/environment/graph.ts +0 -588
- package/src/environment/inspection.ts +0 -107
- package/src/environment/lifecycle.ts +0 -124
- package/src/environment/readiness.ts +0 -76
- package/src/environment/signature.ts +0 -185
- package/src/extract/__tests__/directional-csm-domain.unit.test.ts +0 -391
- package/src/extract/__tests__/environment-source.test.ts +0 -105
- package/src/extract/__tests__/schema-readers.unit.test.ts +0 -16
- package/src/extract/directional-csm.ts +0 -959
- package/src/extract/index.ts +0 -10
- package/src/extract/material-interface.ts +0 -604
- package/src/extract/schema-readers.ts +0 -27
- package/src/features/graph-contribution.ts +0 -577
- package/src/features/index.ts +0 -100
- package/src/features/morph/index.ts +0 -24
- package/src/features/morph/morph-bounds.ts +0 -123
- package/src/features/scene-temporal.ts +0 -274
- package/src/features/taa-resolve.ts +0 -244
- package/src/frame-chain.ts +0 -21
- package/src/hdrp-cluster-membership.ts +0 -70
- package/src/ibl/cubemap-projection.ts +0 -60
- package/src/ibl/face-uniforms.ts +0 -150
- package/src/mesh-update-errors.ts +0 -113
- package/src/mipmap-generator.ts +0 -244
- package/src/param-schema-projection-census.ts +0 -73
- package/src/persistent-render-scene.ts +0 -1752
- package/src/pipeline/index.ts +0 -40
- package/src/pipeline-errors.ts +0 -172
- package/src/prepare/__tests__/schema-readers.unit.test.ts +0 -16
- package/src/prepare/index.ts +0 -8
- package/src/prepare/schema-readers.ts +0 -20
- package/src/record/__tests__/environment-record.test.ts +0 -35
- package/src/record/__tests__/frame-targets.unit.test.ts +0 -54
- package/src/record/__tests__/membership-timing.unit.test.ts +0 -524
- package/src/record/__tests__/render-submission.integration.test.ts +0 -76
- package/src/record/__tests__/render-submission.perf.test.ts +0 -141
- package/src/record/__tests__/shadow-submit-mode.unit.test.ts +0 -88
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +0 -101
- package/src/record/frame-observation.ts +0 -122
- package/src/record/index.ts +0 -15
- package/src/record/main-pass-skin.ts +0 -51
- package/src/record/main-pass-sprite.ts +0 -166
- package/src/record/material-payload.ts +0 -292
- package/src/record/material-slot-plan.ts +0 -68
- package/src/record/membership-timing.ts +0 -1012
- package/src/record/shadow-caster-uniform.ts +0 -37
- package/src/record/shadow-submit-mode.ts +0 -277
- package/src/render-dispatch-membership.ts +0 -155
- package/src/render-pipeline-context.ts +0 -332
- package/src/render-pipeline-target.ts +0 -96
- package/src/render-scene-projection.ts +0 -1738
- package/src/render-system-fold.ts +0 -531
- package/src/renderer/asset-service.ts +0 -32
- package/src/renderer/backend-selection.ts +0 -121
- package/src/renderer/environment-classify.ts +0 -30
- package/src/renderer/environment-error.ts +0 -19
- package/src/renderer/material/pipeline-projection.ts +0 -140
- package/src/renderer.ts +0 -940
- package/src/scene-utils/collect-subtree.ts +0 -40
- package/src/ssao-data.ts +0 -106
- package/src/surface-format.ts +0 -37
- package/src/taa-history-store.ts +0 -429
- package/src/temporal-coverage.ts +0 -106
- package/src/temporal-frame-transaction.ts +0 -301
- package/src/temporal-inspection.ts +0 -194
- package/src/temporal-view.ts +0 -174
- package/src/tilemap/resolve-tileset-runtime.ts +0 -72
|
@@ -13,59 +13,32 @@ import type {
|
|
|
13
13
|
Result,
|
|
14
14
|
RhiDevice,
|
|
15
15
|
ShaderModule,
|
|
16
|
+
TextureFormat,
|
|
16
17
|
} from '@forgeax/engine-rhi';
|
|
17
18
|
import { err, ok, RhiError } from '@forgeax/engine-rhi';
|
|
18
|
-
import {
|
|
19
|
+
import type { MaterialRenderState } from '@forgeax/engine-types';
|
|
20
|
+
import type { MeshGpuHandles } from '../device/gpu-residency';
|
|
19
21
|
import { GPU_SCENE_WGSL } from '../gpu-scene-schema';
|
|
20
22
|
import {
|
|
21
23
|
GPU_BUFFER_USAGE_COPY_DST,
|
|
22
24
|
GPU_BUFFER_USAGE_INDEX,
|
|
23
|
-
GPU_BUFFER_USAGE_UNIFORM,
|
|
24
25
|
GPU_BUFFER_USAGE_VERTEX,
|
|
25
26
|
} from '../gpu-usage';
|
|
26
|
-
import type {
|
|
27
|
+
import type { GpuDrivenProductionInspection } from '../inspection-types';
|
|
27
28
|
import type { PipelineBuilderShaderModuleFactory } from '../pipeline-builder';
|
|
28
|
-
import {
|
|
29
|
-
import
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
} from '../render-
|
|
34
|
-
import type {
|
|
35
|
-
import {
|
|
36
|
-
buildRenderVisibilityViewDescriptors,
|
|
37
|
-
type CameraSnapshot,
|
|
38
|
-
type ExtractedFrame,
|
|
39
|
-
type RenderableSnapshot,
|
|
40
|
-
} from '../render-system-extract';
|
|
41
|
-
import {
|
|
42
|
-
buildBatchAlignedSubmission,
|
|
43
|
-
buildSubmissionCandidateMembership,
|
|
44
|
-
type GpuDrivenBatch,
|
|
45
|
-
type GpuDrivenCandidate,
|
|
46
|
-
type SubmissionCandidateMembership,
|
|
47
|
-
type SubmissionPlan,
|
|
48
|
-
} from './batch-topology';
|
|
49
|
-
import {
|
|
50
|
-
type CpuMultiViewVisibilityResult,
|
|
51
|
-
type CpuVisibilityCandidate,
|
|
52
|
-
executeCpuMultiViewVisibility,
|
|
53
|
-
GpuDrivenView,
|
|
54
|
-
} from './view-gpu';
|
|
29
|
+
import { worldEntityKey } from '../record/frame-snapshot';
|
|
30
|
+
import { geometryRenderStateForTopology } from '../record/main-pass-material';
|
|
31
|
+
import type { CameraSnapshot } from '../render-contract';
|
|
32
|
+
import type { RenderPipelineFrame, RenderPipelineGpuDrivenProjection } from '../render-pipeline';
|
|
33
|
+
import type { RenderableSnapshot } from '../render-system-extract';
|
|
34
|
+
import type { PersistentGpuDrivenState } from '../scene/render-scene';
|
|
35
|
+
import type { GpuDrivenBatch, SubmissionPlan } from './batch-topology';
|
|
36
|
+
import { GpuDrivenView } from './view-gpu';
|
|
55
37
|
|
|
56
38
|
const VERTEX_STAGE = 0x1;
|
|
57
39
|
const FRAGMENT_STAGE = 0x2;
|
|
58
40
|
const EMPTY_RESOURCE_CLASS = JSON.stringify({ textures: [], samplers: [], video: [] });
|
|
59
41
|
|
|
60
|
-
function supportsRigidGpuDrivenProjection(mesh: MeshGpuHandles): boolean {
|
|
61
|
-
const attributes = mesh.layoutProjection.attributes;
|
|
62
|
-
const required = ['position', 'normal', 'uv', 'tangent'] as const;
|
|
63
|
-
return (
|
|
64
|
-
attributes.length === required.length &&
|
|
65
|
-
attributes.every((attribute, index) => attribute.key === required[index])
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
42
|
export const GPU_DRIVEN_RIGID_UNLIT_WGSL = /* wgsl */ `
|
|
70
43
|
${GPU_SCENE_WGSL}
|
|
71
44
|
|
|
@@ -110,45 +83,6 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
110
83
|
}
|
|
111
84
|
`;
|
|
112
85
|
|
|
113
|
-
/**
|
|
114
|
-
* Depth-only shadow raster companion for the shared GPU Scene visibility
|
|
115
|
-
* buffers. It deliberately has no material-dependent fragment stage: alpha
|
|
116
|
-
* test and custom ShadowCaster variants stay on the CPU contract until their
|
|
117
|
-
* own batch shader is available. Opaque casters use the same primitive,
|
|
118
|
-
* instance, transform and compact-visible tables as the main view.
|
|
119
|
-
*/
|
|
120
|
-
export const GPU_DRIVEN_SHADOW_WGSL = /* wgsl */ `
|
|
121
|
-
${GPU_SCENE_WGSL}
|
|
122
|
-
|
|
123
|
-
struct ShadowBatch {
|
|
124
|
-
lightViewProj: mat4x4<f32>,
|
|
125
|
-
visibleBase: u32,
|
|
126
|
-
pad0: u32,
|
|
127
|
-
pad1: u32,
|
|
128
|
-
pad2: u32,
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
@group(2) @binding(0) var<storage, read> primitives: array<GpuScenePrimitive>;
|
|
132
|
-
@group(2) @binding(1) var<storage, read> instances: array<GpuSceneInstance>;
|
|
133
|
-
@group(2) @binding(2) var<storage, read> transforms: array<GpuSceneTransform>;
|
|
134
|
-
@group(2) @binding(3) var<storage, read> visibleItems: array<vec2<u32>>;
|
|
135
|
-
@group(2) @binding(4) var<uniform> shadowBatch: ShadowBatch;
|
|
136
|
-
|
|
137
|
-
struct VertexInput {
|
|
138
|
-
@location(0) position: vec3<f32>,
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
@vertex
|
|
142
|
-
fn vs_main(input: VertexInput, @builtin(instance_index) instanceIndex: u32) -> @builtin(position) vec4<f32> {
|
|
143
|
-
let visible = visibleItems[shadowBatch.visibleBase + instanceIndex];
|
|
144
|
-
let sceneInstance = instances[visible.x];
|
|
145
|
-
let primitive = primitives[sceneInstance.primitiveIndex];
|
|
146
|
-
let world = transforms[primitive.transformIndex].currentWorld *
|
|
147
|
-
transforms[sceneInstance.transformIndex].currentWorld;
|
|
148
|
-
return shadowBatch.lightViewProj * world * vec4<f32>(input.position, 1.0);
|
|
149
|
-
}
|
|
150
|
-
`;
|
|
151
|
-
|
|
152
86
|
interface PreparedBatch {
|
|
153
87
|
readonly batch: GpuDrivenBatch;
|
|
154
88
|
readonly mesh: MeshGpuHandles;
|
|
@@ -199,85 +133,19 @@ function activeFrustum(camera: CameraSnapshot): Float32Array {
|
|
|
199
133
|
);
|
|
200
134
|
}
|
|
201
135
|
|
|
202
|
-
|
|
203
|
-
| 'missing-local-bounds-capability-lane'
|
|
204
|
-
| 'skinned-capability-lane'
|
|
205
|
-
| 'sprite-capability-lane'
|
|
206
|
-
| 'not-geometry-queue'
|
|
207
|
-
| 'unsafe-ordering'
|
|
208
|
-
| 'pbr-capability-lane'
|
|
209
|
-
| 'alpha-test-capability-lane'
|
|
210
|
-
| 'resource-bindings-capability-lane'
|
|
211
|
-
| 'transparent';
|
|
212
|
-
|
|
213
|
-
export interface GpuDrivenRasterEligibility {
|
|
214
|
-
readonly eligible: boolean;
|
|
215
|
-
readonly reason: GpuDrivenRasterEligibilityReason | undefined;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* The current shader remains a deliberately narrow capability lane. Semantic
|
|
220
|
-
* batch keys still retain PBR/alpha/resource/double-sided identity so those
|
|
221
|
-
* objects can share the CPU/shadow contract without being misreported as
|
|
222
|
-
* rigid-unlit GPU-owned raster work.
|
|
223
|
-
*/
|
|
224
|
-
export function gpuDrivenRasterEligibility(
|
|
225
|
-
snapshot: RenderableSnapshot,
|
|
226
|
-
batch: GpuDrivenBatch,
|
|
227
|
-
): GpuDrivenRasterEligibility {
|
|
136
|
+
function productionEligible(snapshot: RenderableSnapshot, batch: GpuDrivenBatch): boolean {
|
|
228
137
|
const material = snapshot.materials[batch.key.materialSlot] ?? snapshot.material;
|
|
229
138
|
const shader = material.materialShaderId ?? 'forgeax::default-unlit';
|
|
230
|
-
if (snapshot.localAabb === undefined) {
|
|
231
|
-
return { eligible: false, reason: 'missing-local-bounds-capability-lane' };
|
|
232
|
-
}
|
|
233
|
-
if (snapshot.skin !== undefined) return { eligible: false, reason: 'skinned-capability-lane' };
|
|
234
|
-
if (snapshot.spriteInstances !== undefined) {
|
|
235
|
-
return { eligible: false, reason: 'sprite-capability-lane' };
|
|
236
|
-
}
|
|
237
|
-
if (batch.key.queue !== RenderQueue.Geometry) {
|
|
238
|
-
return { eligible: false, reason: 'not-geometry-queue' };
|
|
239
|
-
}
|
|
240
|
-
if (!orderSafe(material.renderState)) return { eligible: false, reason: 'unsafe-ordering' };
|
|
241
|
-
if (batch.key.pbr || shader !== 'forgeax::default-unlit') {
|
|
242
|
-
return { eligible: false, reason: 'pbr-capability-lane' };
|
|
243
|
-
}
|
|
244
|
-
if (batch.key.alphaTest) return { eligible: false, reason: 'alpha-test-capability-lane' };
|
|
245
|
-
if (
|
|
246
|
-
batch.key.materialResourceClass !== EMPTY_RESOURCE_CLASS ||
|
|
247
|
-
material.baseColorTexture !== undefined
|
|
248
|
-
) {
|
|
249
|
-
return { eligible: false, reason: 'resource-bindings-capability-lane' };
|
|
250
|
-
}
|
|
251
|
-
if (material.transparent === true) return { eligible: false, reason: 'transparent' };
|
|
252
|
-
return { eligible: true, reason: undefined };
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function productionEligible(snapshot: RenderableSnapshot, batch: GpuDrivenBatch): boolean {
|
|
256
|
-
return gpuDrivenRasterEligibility(snapshot, batch).eligible;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function sameNumberArray(left: readonly number[], right: readonly number[]): boolean {
|
|
260
|
-
if (left.length !== right.length) return false;
|
|
261
|
-
for (let index = 0; index < left.length; index += 1) {
|
|
262
|
-
if (left[index] !== right[index]) return false;
|
|
263
|
-
}
|
|
264
|
-
return true;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function orderSafe(renderState: MaterialRenderState | undefined): boolean {
|
|
268
|
-
if (renderState === undefined) return true;
|
|
269
139
|
return (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
renderState.stencilReadMask === undefined &&
|
|
275
|
-
renderState.stencilWriteMask === undefined
|
|
140
|
+
shader === 'forgeax::default-unlit' &&
|
|
141
|
+
batch.key.materialResourceClass === EMPTY_RESOURCE_CLASS &&
|
|
142
|
+
material.baseColorTexture === undefined &&
|
|
143
|
+
material.transparent !== true
|
|
276
144
|
);
|
|
277
145
|
}
|
|
278
146
|
|
|
279
147
|
function meshSupportsBatch(mesh: MeshGpuHandles, batch: GpuDrivenBatch): boolean {
|
|
280
|
-
if (
|
|
148
|
+
if (mesh.layoutProjection.arrayStride !== 48) return false;
|
|
281
149
|
return batch.key.drawKind === 'indexed'
|
|
282
150
|
? mesh.indexed && mesh.indexBuffer !== null
|
|
283
151
|
: !mesh.indexed;
|
|
@@ -289,159 +157,72 @@ function filteredPlan(
|
|
|
289
157
|
meshes: ReadonlyMap<number, MeshGpuHandles>,
|
|
290
158
|
): {
|
|
291
159
|
readonly plan: SubmissionPlan;
|
|
292
|
-
readonly shadowPlan: SubmissionPlan;
|
|
293
160
|
readonly batches: readonly PreparedBatch[];
|
|
294
|
-
readonly
|
|
295
|
-
readonly forwardItemKeys: ReadonlySet<RasterItemKey>;
|
|
161
|
+
readonly entityKeys: ReadonlySet<number>;
|
|
296
162
|
} {
|
|
297
163
|
const slotByPrimitive = new Map(slots.map((slot) => [slot.slot, slot] as const));
|
|
298
|
-
const
|
|
299
|
-
const
|
|
300
|
-
let hasEarlierQueue = false;
|
|
164
|
+
const entityKeys = new Set<number>();
|
|
165
|
+
const eligiblePrimitives = new Set<number>();
|
|
301
166
|
for (const slot of slots) {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
)
|
|
309
|
-
|
|
310
|
-
|
|
167
|
+
const mesh = meshes.get(slot.snapshot.assetHandle);
|
|
168
|
+
const participating = source.batches.filter((batch) =>
|
|
169
|
+
batch.candidates.some((candidate) => candidate.primitiveIndex === slot.slot),
|
|
170
|
+
);
|
|
171
|
+
if (
|
|
172
|
+
mesh !== undefined &&
|
|
173
|
+
participating.length === (slot.snapshot.gpuDrivenDraws?.length ?? 0) &&
|
|
174
|
+
participating.every(
|
|
175
|
+
(batch) => productionEligible(slot.snapshot, batch) && meshSupportsBatch(mesh, batch),
|
|
176
|
+
)
|
|
177
|
+
) {
|
|
178
|
+
eligiblePrimitives.add(slot.slot);
|
|
179
|
+
entityKeys.add(worldEntityKey(slot.snapshot.worldId, slot.snapshot.entityKey));
|
|
311
180
|
}
|
|
312
181
|
}
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
const
|
|
316
|
-
const renderStateByBatch = new Map<number, MaterialRenderState | undefined>();
|
|
182
|
+
const batches: PreparedBatch[] = [];
|
|
183
|
+
let visibleBase = 0;
|
|
184
|
+
const filteredBatches: GpuDrivenBatch[] = [];
|
|
317
185
|
for (const batch of source.batches) {
|
|
318
|
-
const shadowCandidates = batch.candidates.filter(
|
|
319
|
-
(candidate) => slotByPrimitive.has(candidate.primitiveIndex) && batch.key.shadowCaster,
|
|
320
|
-
);
|
|
321
|
-
if (shadowCandidates.length > 0) {
|
|
322
|
-
shadowCandidatesByBatch.set(batch.batchId, Object.freeze(shadowCandidates));
|
|
323
|
-
}
|
|
324
186
|
const candidates = batch.candidates.filter((candidate) => {
|
|
325
187
|
const slot = slotByPrimitive.get(candidate.primitiveIndex);
|
|
326
|
-
if (slot === undefined || !
|
|
188
|
+
if (slot === undefined || !eligiblePrimitives.has(slot.slot)) return false;
|
|
327
189
|
const mesh = meshes.get(slot.snapshot.assetHandle);
|
|
328
|
-
|
|
329
|
-
const draw = slot.snapshot.gpuDrivenDraws?.[candidate.drawItemIndex];
|
|
330
|
-
if (draw === undefined) return false;
|
|
331
|
-
itemKeys.add(
|
|
332
|
-
rasterItemKey(
|
|
333
|
-
slot.snapshot.worldId,
|
|
334
|
-
slot.snapshot.entityKey,
|
|
335
|
-
draw.submeshIndex,
|
|
336
|
-
draw.passIndex,
|
|
337
|
-
),
|
|
338
|
-
);
|
|
339
|
-
return true;
|
|
190
|
+
return mesh !== undefined && meshSupportsBatch(mesh, batch);
|
|
340
191
|
});
|
|
341
192
|
if (candidates.length === 0) continue;
|
|
193
|
+
visibleBase = Math.ceil(visibleBase / 64) * 64;
|
|
194
|
+
const filtered: GpuDrivenBatch = Object.freeze({
|
|
195
|
+
...batch,
|
|
196
|
+
candidates: Object.freeze(candidates),
|
|
197
|
+
visibleBase,
|
|
198
|
+
visibleCapacity: candidates.length,
|
|
199
|
+
});
|
|
200
|
+
visibleBase += candidates.length;
|
|
342
201
|
const first = slotByPrimitive.get(candidates[0]?.primitiveIndex ?? -1);
|
|
343
202
|
const mesh = first === undefined ? undefined : meshes.get(first.snapshot.assetHandle);
|
|
344
203
|
if (mesh === undefined || first === undefined) continue;
|
|
345
|
-
|
|
346
|
-
meshByBatch.set(batch.batchId, mesh);
|
|
204
|
+
filteredBatches.push(filtered);
|
|
347
205
|
const material = first.snapshot.materials[batch.key.materialSlot] ?? first.snapshot.material;
|
|
348
|
-
renderStateByBatch.set(batch.batchId, material.renderState);
|
|
349
|
-
}
|
|
350
|
-
const sourceShadowPlan = buildBatchAlignedSubmission(source, shadowCandidatesByBatch);
|
|
351
|
-
// The typed graph encodes the GPU Geometry lane before CPU recording in the
|
|
352
|
-
// same raster pass. If an earlier queue or an ineligible Geometry item is
|
|
353
|
-
// present, publishing only a subset would change stable queue order. Fail
|
|
354
|
-
// closed for the whole GPU lane and let the CPU path own every item.
|
|
355
|
-
if (hasEarlierQueue || itemKeys.size !== forwardItemKeys.size) {
|
|
356
|
-
return {
|
|
357
|
-
plan: Object.freeze({
|
|
358
|
-
revision: source.revision,
|
|
359
|
-
batches: Object.freeze([]),
|
|
360
|
-
candidateCount: 0,
|
|
361
|
-
visibleCapacity: 0,
|
|
362
|
-
}),
|
|
363
|
-
shadowPlan: sourceShadowPlan,
|
|
364
|
-
batches: Object.freeze([]),
|
|
365
|
-
itemKeys: new Set<RasterItemKey>(),
|
|
366
|
-
forwardItemKeys,
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
const plan = buildBatchAlignedSubmission(source, candidatesByBatch);
|
|
370
|
-
const batches: PreparedBatch[] = [];
|
|
371
|
-
for (const batch of plan.batches) {
|
|
372
|
-
const mesh = meshByBatch.get(batch.batchId);
|
|
373
|
-
if (mesh === undefined) continue;
|
|
374
206
|
batches.push({
|
|
375
|
-
batch,
|
|
207
|
+
batch: filtered,
|
|
376
208
|
mesh,
|
|
377
|
-
renderState:
|
|
209
|
+
renderState: geometryRenderStateForTopology(batch.key.topology, material.renderState),
|
|
378
210
|
});
|
|
379
211
|
}
|
|
380
212
|
return {
|
|
381
|
-
plan
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
213
|
+
plan: Object.freeze({
|
|
214
|
+
revision: source.revision,
|
|
215
|
+
batches: Object.freeze(filteredBatches),
|
|
216
|
+
candidateCount: filteredBatches.reduce((total, batch) => total + batch.candidates.length, 0),
|
|
217
|
+
visibleCapacity: visibleBase,
|
|
218
|
+
}),
|
|
386
219
|
batches: Object.freeze(batches),
|
|
387
|
-
|
|
388
|
-
forwardItemKeys,
|
|
220
|
+
entityKeys,
|
|
389
221
|
};
|
|
390
222
|
}
|
|
391
223
|
|
|
392
|
-
function filterShadowSubmissionBySlots(
|
|
393
|
-
source: SubmissionPlan,
|
|
394
|
-
shadowCasterSlotIndices: ReadonlySet<number> | undefined,
|
|
395
|
-
): SubmissionPlan {
|
|
396
|
-
if (shadowCasterSlotIndices === undefined) return source;
|
|
397
|
-
const candidatesByBatch = new Map<number, readonly GpuDrivenCandidate[]>();
|
|
398
|
-
for (const batch of source.batches) {
|
|
399
|
-
const candidates = batch.candidates.filter((candidate) =>
|
|
400
|
-
shadowCasterSlotIndices.has(candidate.primitiveIndex),
|
|
401
|
-
);
|
|
402
|
-
if (candidates.length > 0) {
|
|
403
|
-
candidatesByBatch.set(batch.batchId, Object.freeze(candidates));
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
return buildBatchAlignedSubmission(source, candidatesByBatch);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
224
|
type FilteredProductionPlan = ReturnType<typeof filteredPlan>;
|
|
410
225
|
|
|
411
|
-
export interface GpuDrivenProductionInspection {
|
|
412
|
-
readonly gpuOwnedSnapshotsMaterialized: number;
|
|
413
|
-
readonly filteredPlanBuilds: number;
|
|
414
|
-
readonly gpuOwnedItemCount: number;
|
|
415
|
-
readonly candidateUploadBytes: number;
|
|
416
|
-
readonly batchUploadBytes: number;
|
|
417
|
-
readonly viewConstantsUploadBytes: number;
|
|
418
|
-
readonly batchBindGroupCreates: number;
|
|
419
|
-
readonly viewBindGroupCreates: number;
|
|
420
|
-
readonly topologyRevision: number | undefined;
|
|
421
|
-
readonly validatedGpuOwnedRows: number;
|
|
422
|
-
readonly cpuFallbackDrawItems: number;
|
|
423
|
-
readonly cpuVisibility: CpuMultiViewVisibilityResult | undefined;
|
|
424
|
-
readonly shadowBatchCount: number;
|
|
425
|
-
readonly shadowCandidateCount: number;
|
|
426
|
-
readonly shadowDrawCount: number;
|
|
427
|
-
readonly faults: readonly GpuDrivenVisibilityFault[];
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
export type GpuDrivenVisibilityFaultCode =
|
|
431
|
-
| 'visibility-overflow'
|
|
432
|
-
| 'gpu-capability-unavailable'
|
|
433
|
-
| 'gpu-scene-fact-unavailable'
|
|
434
|
-
| 'device-recovery-required'
|
|
435
|
-
| 'gpu-resource-failed';
|
|
436
|
-
|
|
437
|
-
export interface GpuDrivenVisibilityFault {
|
|
438
|
-
readonly code: GpuDrivenVisibilityFaultCode;
|
|
439
|
-
readonly viewId: string;
|
|
440
|
-
readonly revision: number;
|
|
441
|
-
readonly fallback: 'cpu-batch-contract' | 'scene-rebuild';
|
|
442
|
-
readonly detail: string;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
226
|
class GpuDrivenRigidRaster {
|
|
446
227
|
private readonly pipelines = new Map<string, RenderPipeline>();
|
|
447
228
|
|
|
@@ -492,7 +273,7 @@ class GpuDrivenRigidRaster {
|
|
|
492
273
|
}
|
|
493
274
|
|
|
494
275
|
pipeline(
|
|
495
|
-
format:
|
|
276
|
+
format: TextureFormat,
|
|
496
277
|
sampleCount: 1 | 4,
|
|
497
278
|
vertexStride: number,
|
|
498
279
|
topology: GpuDrivenBatch['key']['topology'],
|
|
@@ -504,9 +285,9 @@ class GpuDrivenRigidRaster {
|
|
|
504
285
|
if (cached !== undefined) return ok(cached);
|
|
505
286
|
const created = this.device.createRenderPipeline({
|
|
506
287
|
label: `gpu-driven-rigid-unlit.${key}`,
|
|
507
|
-
layout: this.pipelineLayout
|
|
288
|
+
layout: this.pipelineLayout,
|
|
508
289
|
vertex: {
|
|
509
|
-
module: this.module
|
|
290
|
+
module: this.module,
|
|
510
291
|
entryPoint: 'vs_main',
|
|
511
292
|
buffers: [
|
|
512
293
|
{
|
|
@@ -517,17 +298,17 @@ class GpuDrivenRigidRaster {
|
|
|
517
298
|
],
|
|
518
299
|
},
|
|
519
300
|
fragment: {
|
|
520
|
-
module: this.module
|
|
301
|
+
module: this.module,
|
|
521
302
|
entryPoint: 'fs_main',
|
|
522
303
|
targets: [
|
|
523
304
|
{
|
|
524
|
-
format
|
|
305
|
+
format,
|
|
525
306
|
...(renderState?.blend === undefined ? {} : { blend: renderState.blend }),
|
|
526
307
|
},
|
|
527
308
|
],
|
|
528
309
|
},
|
|
529
310
|
primitive: {
|
|
530
|
-
topology
|
|
311
|
+
topology,
|
|
531
312
|
cullMode: renderState?.cullMode ?? 'back',
|
|
532
313
|
frontFace: renderState?.frontFace ?? 'ccw',
|
|
533
314
|
...(stripIndexFormat === undefined ? {} : { stripIndexFormat }),
|
|
@@ -594,292 +375,22 @@ class GpuDrivenRigidRaster {
|
|
|
594
375
|
}
|
|
595
376
|
}
|
|
596
377
|
|
|
597
|
-
interface PreparedShadowBatch {
|
|
598
|
-
readonly batch: GpuDrivenBatch;
|
|
599
|
-
readonly mesh: MeshGpuHandles;
|
|
600
|
-
readonly pipeline: RenderPipeline;
|
|
601
|
-
readonly uniformOffset: number;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
interface PreparedShadowView {
|
|
605
|
-
readonly cascadeIndex: number;
|
|
606
|
-
readonly view: GpuDrivenView;
|
|
607
|
-
readonly plan: SubmissionPlan;
|
|
608
|
-
readonly batches: readonly PreparedShadowBatch[];
|
|
609
|
-
readonly bindGroup: BindGroup;
|
|
610
|
-
readonly graphLabel: string;
|
|
611
|
-
readonly graphResources?: import('./view-gpu').GpuDrivenViewGraphResources;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
class GpuDrivenShadowRaster {
|
|
615
|
-
private readonly pipelines = new Map<string, RenderPipeline>();
|
|
616
|
-
private readonly uniformBuffers = new Set<import('@forgeax/engine-rhi').Buffer>();
|
|
617
|
-
private readonly uniformByCascade = new Map<number, import('@forgeax/engine-rhi').Buffer>();
|
|
618
|
-
private readonly uniformCapacities = new Map<number, number>();
|
|
619
|
-
|
|
620
|
-
private constructor(
|
|
621
|
-
private readonly device: RhiDevice,
|
|
622
|
-
private readonly layout: BindGroupLayout,
|
|
623
|
-
private readonly pipelineLayout: import('@forgeax/engine-rhi').PipelineLayout,
|
|
624
|
-
private readonly module: ShaderModule,
|
|
625
|
-
) {}
|
|
626
|
-
|
|
627
|
-
static create(input: {
|
|
628
|
-
readonly device: RhiDevice;
|
|
629
|
-
readonly shaderModuleFactory: PipelineBuilderShaderModuleFactory;
|
|
630
|
-
readonly viewBindGroupLayout: BindGroupLayout;
|
|
631
|
-
readonly materialBindGroupLayout: BindGroupLayout;
|
|
632
|
-
}): Result<GpuDrivenShadowRaster, RhiError> {
|
|
633
|
-
const layout = input.device.createBindGroupLayout({
|
|
634
|
-
label: 'gpu-driven-shadow-raster-bgl',
|
|
635
|
-
entries: [
|
|
636
|
-
{ binding: 0, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
|
|
637
|
-
{ binding: 1, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
|
|
638
|
-
{ binding: 2, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
|
|
639
|
-
{ binding: 3, visibility: VERTEX_STAGE, buffer: { type: 'read-only-storage' } },
|
|
640
|
-
{
|
|
641
|
-
binding: 4,
|
|
642
|
-
visibility: VERTEX_STAGE,
|
|
643
|
-
buffer: { type: 'uniform', hasDynamicOffset: true },
|
|
644
|
-
},
|
|
645
|
-
],
|
|
646
|
-
});
|
|
647
|
-
if (!layout.ok) return layout;
|
|
648
|
-
const pipelineLayout = input.device.createPipelineLayout({
|
|
649
|
-
label: 'gpu-driven-shadow-raster-pl',
|
|
650
|
-
bindGroupLayouts: [input.viewBindGroupLayout, input.materialBindGroupLayout, layout.value],
|
|
651
|
-
});
|
|
652
|
-
if (!pipelineLayout.ok) return pipelineLayout;
|
|
653
|
-
const module = input.shaderModuleFactory.createShaderModule({
|
|
654
|
-
label: 'gpu-driven-shadow-raster',
|
|
655
|
-
code: GPU_DRIVEN_SHADOW_WGSL,
|
|
656
|
-
});
|
|
657
|
-
if (!module.ok) return module;
|
|
658
|
-
return ok(
|
|
659
|
-
new GpuDrivenShadowRaster(input.device, layout.value, pipelineLayout.value, module.value),
|
|
660
|
-
);
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
prepareView(input: {
|
|
664
|
-
readonly cascadeIndex: number;
|
|
665
|
-
readonly scene: PersistentGpuDrivenState['scene'];
|
|
666
|
-
readonly view: GpuDrivenView;
|
|
667
|
-
readonly plan: SubmissionPlan;
|
|
668
|
-
readonly lightViewProj: Float32Array;
|
|
669
|
-
readonly meshes: ReadonlyMap<number, MeshGpuHandles>;
|
|
670
|
-
readonly graphLabel: string;
|
|
671
|
-
}): Result<PreparedShadowView | undefined, RhiError> {
|
|
672
|
-
const eligibleBatches: Array<{
|
|
673
|
-
readonly batch: GpuDrivenBatch;
|
|
674
|
-
readonly mesh: MeshGpuHandles;
|
|
675
|
-
}> = [];
|
|
676
|
-
for (const batch of input.plan.batches) {
|
|
677
|
-
// The GPU shadow shader is the opaque rigid capability lane. Alpha-test,
|
|
678
|
-
// custom material shadow shaders, non-rigid geometry and line/point
|
|
679
|
-
// topology remain on the same batch-aligned CPU fallback contract.
|
|
680
|
-
if (batch.key.alphaTest) continue;
|
|
681
|
-
if (batch.key.topology !== 'triangle-list' && batch.key.topology !== 'triangle-strip') {
|
|
682
|
-
continue;
|
|
683
|
-
}
|
|
684
|
-
const mesh = input.meshes.get(batch.key.assetHandle);
|
|
685
|
-
if (mesh === undefined || !supportsRigidGpuDrivenProjection(mesh)) continue;
|
|
686
|
-
if (batch.key.drawKind === 'indexed' && (!mesh.indexed || mesh.indexBuffer === null)) {
|
|
687
|
-
continue;
|
|
688
|
-
}
|
|
689
|
-
if (batch.key.drawKind === 'non-indexed' && mesh.indexed) continue;
|
|
690
|
-
eligibleBatches.push({ batch, mesh });
|
|
691
|
-
}
|
|
692
|
-
if (eligibleBatches.length === 0 || input.view.visibleBuffer === undefined)
|
|
693
|
-
return ok(undefined);
|
|
694
|
-
|
|
695
|
-
const requiredBytes = Math.max(256, eligibleBatches.length * 256);
|
|
696
|
-
let uniformBuffer = this.uniformByCascade.get(input.cascadeIndex);
|
|
697
|
-
const currentCapacity = this.uniformCapacities.get(input.cascadeIndex) ?? 0;
|
|
698
|
-
if (uniformBuffer === undefined || currentCapacity < requiredBytes) {
|
|
699
|
-
const created = this.device.createBuffer({
|
|
700
|
-
label: `gpu-driven-shadow-cascade-${input.cascadeIndex}-uniforms`,
|
|
701
|
-
size: requiredBytes,
|
|
702
|
-
usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
|
|
703
|
-
mappedAtCreation: false,
|
|
704
|
-
});
|
|
705
|
-
if (!created.ok) return created;
|
|
706
|
-
uniformBuffer = created.value;
|
|
707
|
-
this.uniformBuffers.add(uniformBuffer);
|
|
708
|
-
this.uniformByCascade.set(input.cascadeIndex, uniformBuffer);
|
|
709
|
-
this.uniformCapacities.set(input.cascadeIndex, requiredBytes);
|
|
710
|
-
}
|
|
711
|
-
const payload = new Uint8Array(requiredBytes);
|
|
712
|
-
for (let index = 0; index < eligibleBatches.length; index += 1) {
|
|
713
|
-
const item = eligibleBatches[index];
|
|
714
|
-
if (item === undefined) continue;
|
|
715
|
-
const offset = index * 256;
|
|
716
|
-
new Float32Array(payload.buffer, offset, 16).set(input.lightViewProj.subarray(0, 16));
|
|
717
|
-
new DataView(payload.buffer).setUint32(offset + 64, item.batch.visibleBase, true);
|
|
718
|
-
}
|
|
719
|
-
const write = this.device.queue.writeBuffer(uniformBuffer, 0, payload);
|
|
720
|
-
if (!write.ok) return write;
|
|
721
|
-
const visible = input.view.visibleBuffer;
|
|
722
|
-
const binding = this.device.createBindGroup({
|
|
723
|
-
label: `gpu-driven-shadow-cascade-${input.cascadeIndex}-bg`,
|
|
724
|
-
layout: this.layout,
|
|
725
|
-
entries: [
|
|
726
|
-
{ binding: 0, resource: bufferBinding(input.scene.primitiveBuffer) },
|
|
727
|
-
{ binding: 1, resource: bufferBinding(input.scene.instanceBuffer) },
|
|
728
|
-
{ binding: 2, resource: bufferBinding(input.scene.transformBuffer) },
|
|
729
|
-
{ binding: 3, resource: bufferBinding(visible) },
|
|
730
|
-
{
|
|
731
|
-
binding: 4,
|
|
732
|
-
resource: {
|
|
733
|
-
kind: 'buffer',
|
|
734
|
-
value: { buffer: uniformBuffer, offset: 0, size: 80 },
|
|
735
|
-
},
|
|
736
|
-
},
|
|
737
|
-
],
|
|
738
|
-
});
|
|
739
|
-
if (!binding.ok) return binding;
|
|
740
|
-
const batches: PreparedShadowBatch[] = [];
|
|
741
|
-
for (let index = 0; index < eligibleBatches.length; index += 1) {
|
|
742
|
-
const item = eligibleBatches[index];
|
|
743
|
-
if (item === undefined) continue;
|
|
744
|
-
const pipeline = this.pipeline(item.mesh, item.batch);
|
|
745
|
-
if (!pipeline.ok) return pipeline;
|
|
746
|
-
batches.push({
|
|
747
|
-
batch: item.batch,
|
|
748
|
-
mesh: item.mesh,
|
|
749
|
-
pipeline: pipeline.value,
|
|
750
|
-
uniformOffset: index * 256,
|
|
751
|
-
});
|
|
752
|
-
}
|
|
753
|
-
return ok({
|
|
754
|
-
cascadeIndex: input.cascadeIndex,
|
|
755
|
-
view: input.view,
|
|
756
|
-
plan: input.plan,
|
|
757
|
-
batches: Object.freeze(batches),
|
|
758
|
-
bindGroup: binding.value,
|
|
759
|
-
graphLabel: input.graphLabel,
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
encode(
|
|
764
|
-
prepared: PreparedShadowView,
|
|
765
|
-
resources: GraphResourceResolver,
|
|
766
|
-
graphResources: import('./view-gpu').GpuDrivenViewGraphResources,
|
|
767
|
-
pass: import('@forgeax/engine-rhi').RhiRenderPassEncoder,
|
|
768
|
-
): void {
|
|
769
|
-
const indirect = resources.buffer(graphResources.indirect);
|
|
770
|
-
if (!indirect.ok) throw indirect.error;
|
|
771
|
-
let currentPipeline: RenderPipeline | undefined;
|
|
772
|
-
let currentVertex: import('@forgeax/engine-rhi').Buffer | undefined;
|
|
773
|
-
let currentIndex: import('@forgeax/engine-rhi').Buffer | undefined;
|
|
774
|
-
for (const batch of prepared.batches) {
|
|
775
|
-
if (currentPipeline !== batch.pipeline) {
|
|
776
|
-
pass.setPipeline(batch.pipeline);
|
|
777
|
-
currentPipeline = batch.pipeline;
|
|
778
|
-
}
|
|
779
|
-
pass.setBindGroup(2, prepared.bindGroup, [batch.uniformOffset]);
|
|
780
|
-
if (currentVertex !== batch.mesh.vertexBuffer.handle) {
|
|
781
|
-
pass.setVertexBuffer(0, batch.mesh.vertexBuffer.handle);
|
|
782
|
-
currentVertex = batch.mesh.vertexBuffer.handle;
|
|
783
|
-
}
|
|
784
|
-
if (batch.mesh.indexBuffer !== null && batch.mesh.indexed) {
|
|
785
|
-
if (currentIndex !== batch.mesh.indexBuffer.handle) {
|
|
786
|
-
pass.setIndexBuffer(batch.mesh.indexBuffer.handle, batch.mesh.indexFormat);
|
|
787
|
-
currentIndex = batch.mesh.indexBuffer.handle;
|
|
788
|
-
}
|
|
789
|
-
pass.drawIndexedIndirect(indirect.value, batch.batch.indirectOffset);
|
|
790
|
-
} else {
|
|
791
|
-
pass.drawIndirect(indirect.value, batch.batch.indirectOffset);
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
dispose(): void {
|
|
797
|
-
for (const buffer of this.uniformBuffers) this.device.destroyBuffer(buffer);
|
|
798
|
-
this.uniformBuffers.clear();
|
|
799
|
-
this.uniformByCascade.clear();
|
|
800
|
-
this.uniformCapacities.clear();
|
|
801
|
-
this.pipelines.clear();
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
private pipeline(mesh: MeshGpuHandles, batch: GpuDrivenBatch): Result<RenderPipeline, RhiError> {
|
|
805
|
-
const stripIndexFormat =
|
|
806
|
-
batch.key.drawKind === 'indexed' && batch.key.topology === 'triangle-strip'
|
|
807
|
-
? mesh.indexFormat
|
|
808
|
-
: undefined;
|
|
809
|
-
const key = `${batch.key.topology}|${stripIndexFormat ?? ''}|${batch.key.doubleSided ? 'none' : 'back'}`;
|
|
810
|
-
const cached = this.pipelines.get(key);
|
|
811
|
-
if (cached !== undefined) return ok(cached);
|
|
812
|
-
const created = this.device.createRenderPipeline({
|
|
813
|
-
label: `gpu-driven-shadow-${key}`,
|
|
814
|
-
layout: this.pipelineLayout as unknown as GPUPipelineLayout,
|
|
815
|
-
vertex: {
|
|
816
|
-
module: this.module as unknown as GPUShaderModule,
|
|
817
|
-
entryPoint: 'vs_main',
|
|
818
|
-
buffers: [
|
|
819
|
-
{
|
|
820
|
-
arrayStride: 48,
|
|
821
|
-
stepMode: 'vertex',
|
|
822
|
-
attributes: [{ shaderLocation: 0, offset: 0, format: 'float32x3' }],
|
|
823
|
-
},
|
|
824
|
-
],
|
|
825
|
-
},
|
|
826
|
-
primitive: {
|
|
827
|
-
topology: batch.key.topology as GPUPrimitiveTopology,
|
|
828
|
-
cullMode: batch.key.doubleSided ? 'none' : 'back',
|
|
829
|
-
frontFace: 'ccw',
|
|
830
|
-
...(stripIndexFormat === undefined ? {} : { stripIndexFormat }),
|
|
831
|
-
},
|
|
832
|
-
depthStencil: {
|
|
833
|
-
format: 'depth32float',
|
|
834
|
-
depthWriteEnabled: true,
|
|
835
|
-
depthCompare: 'less',
|
|
836
|
-
},
|
|
837
|
-
});
|
|
838
|
-
if (!created.ok) return created;
|
|
839
|
-
this.pipelines.set(key, created.value);
|
|
840
|
-
return created;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
|
|
844
378
|
export interface PreparedGpuDrivenFrame {
|
|
845
379
|
readonly topologySignature: string;
|
|
846
|
-
readonly
|
|
847
|
-
readonly
|
|
848
|
-
/**
|
|
849
|
-
readonly
|
|
380
|
+
readonly entityKeys: ReadonlySet<number>;
|
|
381
|
+
readonly ownsAllRenderables: boolean;
|
|
382
|
+
/** @internal Commits a replacement generation only after graph promotion. */
|
|
383
|
+
readonly _commitResourceReplacement: () => void;
|
|
850
384
|
project(
|
|
851
385
|
graph: RenderGraphBuilder<RenderPipelineFrame>,
|
|
852
|
-
format:
|
|
386
|
+
format: TextureFormat,
|
|
853
387
|
sampleCount: 1 | 4,
|
|
854
388
|
): Result<RenderPipelineGpuDrivenProjection, RenderGraphError | RhiError>;
|
|
855
389
|
}
|
|
856
390
|
|
|
857
|
-
/**
|
|
858
|
-
* Per-view production submission. The batch-aligned plan owns candidate
|
|
859
|
-
* membership; candidateIndexByStableId is a one-way adapter for the existing
|
|
860
|
-
* direct RHI draw encoder and must not be used to generate another view list.
|
|
861
|
-
*/
|
|
862
|
-
export interface MultiViewProductionSubmission {
|
|
863
|
-
readonly source: 'multi-view-indirect';
|
|
864
|
-
readonly viewId: string;
|
|
865
|
-
readonly kind: 'main' | 'cascade';
|
|
866
|
-
readonly cascadeIndex: number | undefined;
|
|
867
|
-
readonly volumeRevision: number | undefined;
|
|
868
|
-
readonly spatialIndexRevision: number | undefined;
|
|
869
|
-
readonly overflow: boolean;
|
|
870
|
-
readonly plan: SubmissionPlan;
|
|
871
|
-
readonly candidateIndexByStableId: ReadonlyMap<number, number>;
|
|
872
|
-
/** Immutable candidate membership adapter shared by CPU shadow fallback and observation. */
|
|
873
|
-
readonly candidateIndices: ReadonlySet<number>;
|
|
874
|
-
readonly faults: readonly GpuDrivenVisibilityFault[];
|
|
875
|
-
}
|
|
876
|
-
|
|
877
391
|
export class GpuDrivenProduction {
|
|
878
392
|
private view: GpuDrivenView | undefined;
|
|
879
393
|
private raster: GpuDrivenRigidRaster | undefined;
|
|
880
|
-
private shadowRaster: GpuDrivenShadowRaster | undefined;
|
|
881
|
-
private readonly shadowViews = new Map<number, GpuDrivenView>();
|
|
882
|
-
private preparedShadowViews: readonly PreparedShadowView[] = [];
|
|
883
394
|
private readonly sceneIdentities = new WeakMap<object, number>();
|
|
884
395
|
private nextSceneIdentity = 1;
|
|
885
396
|
private filteredCache:
|
|
@@ -891,32 +402,10 @@ export class GpuDrivenProduction {
|
|
|
891
402
|
| undefined;
|
|
892
403
|
private gpuOwnedSnapshotsMaterialized = 0;
|
|
893
404
|
private filteredPlanBuilds = 0;
|
|
894
|
-
private
|
|
405
|
+
private gpuOwnedEntityCount = 0;
|
|
895
406
|
private batchBindGroupCreates = 0;
|
|
896
407
|
private validatedGpuOwnedRows = 0;
|
|
897
408
|
private cpuFallbackDrawItems = 0;
|
|
898
|
-
private cpuVisibility: CpuMultiViewVisibilityResult | undefined;
|
|
899
|
-
/** Candidate-domain ShadowCaster membership projected onto persistent slots. */
|
|
900
|
-
private shadowCasterSlotIndices: ReadonlySet<number> | undefined;
|
|
901
|
-
private visibilityViews: readonly import('../render-system-extract').RenderVisibilityViewDescriptor[] =
|
|
902
|
-
[];
|
|
903
|
-
private shadowSubmission: SubmissionPlan | undefined;
|
|
904
|
-
private readonly shadowPlanCache = new Map<
|
|
905
|
-
string,
|
|
906
|
-
{
|
|
907
|
-
readonly source: SubmissionPlan;
|
|
908
|
-
readonly stableIds: readonly number[];
|
|
909
|
-
readonly generations: readonly number[];
|
|
910
|
-
readonly plan: SubmissionPlan;
|
|
911
|
-
}
|
|
912
|
-
>();
|
|
913
|
-
/**
|
|
914
|
-
* Reverse index for the immutable shadow topology. Cascade views provide
|
|
915
|
-
* stable slot ids, so rebuilding a view plan should walk the selected view
|
|
916
|
-
* domain instead of filtering every source candidate for every cascade.
|
|
917
|
-
*/
|
|
918
|
-
private shadowCandidateMembership: SubmissionCandidateMembership | undefined;
|
|
919
|
-
private faults: readonly GpuDrivenVisibilityFault[] = [];
|
|
920
409
|
private signatureCache:
|
|
921
410
|
| {
|
|
922
411
|
readonly filtered: FilteredProductionPlan;
|
|
@@ -932,146 +421,11 @@ export class GpuDrivenProduction {
|
|
|
932
421
|
private readonly shaderModuleFactory: PipelineBuilderShaderModuleFactory,
|
|
933
422
|
) {}
|
|
934
423
|
|
|
935
|
-
prepareCpuVisibility(input: {
|
|
936
|
-
readonly scene: PersistentGpuDrivenState | undefined;
|
|
937
|
-
readonly frame: ExtractedFrame;
|
|
938
|
-
readonly camera: CameraSnapshot | undefined;
|
|
939
|
-
}): CpuMultiViewVisibilityResult | undefined {
|
|
940
|
-
this.faults = [];
|
|
941
|
-
if (input.scene === undefined) {
|
|
942
|
-
this.cpuVisibility = undefined;
|
|
943
|
-
this.visibilityViews = [];
|
|
944
|
-
this.shadowCasterSlotIndices = undefined;
|
|
945
|
-
this.shadowPlanCache.clear();
|
|
946
|
-
this.shadowCandidateMembership = undefined;
|
|
947
|
-
return undefined;
|
|
948
|
-
}
|
|
949
|
-
const descriptors = buildRenderVisibilityViewDescriptors({
|
|
950
|
-
camera: input.camera,
|
|
951
|
-
directionalCsm: input.frame.lights.directionalCsm,
|
|
952
|
-
spatialIndexRevision: input.scene.scene.inspect().spatialIndex?.revision,
|
|
953
|
-
});
|
|
954
|
-
const batchBySlot = new Map<
|
|
955
|
-
number,
|
|
956
|
-
{ readonly batchId: number; readonly instanceOrdinal: number }
|
|
957
|
-
>();
|
|
958
|
-
const capacityByBatch = new Map<number, number>();
|
|
959
|
-
for (const batch of input.scene.plan.batches) {
|
|
960
|
-
capacityByBatch.set(batch.batchId, batch.visibleCapacity);
|
|
961
|
-
for (const candidate of batch.candidates) {
|
|
962
|
-
if (!batchBySlot.has(candidate.primitiveIndex)) {
|
|
963
|
-
batchBySlot.set(candidate.primitiveIndex, {
|
|
964
|
-
batchId: batch.batchId,
|
|
965
|
-
instanceOrdinal: candidate.instanceOrdinal,
|
|
966
|
-
});
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
const candidateDomain = input.frame.candidateDomain;
|
|
971
|
-
const needsCandidateIdentityFallback =
|
|
972
|
-
candidateDomain !== undefined ||
|
|
973
|
-
input.scene.slots.some((slot) => slot.snapshot.candidateIndex === undefined);
|
|
974
|
-
let candidateIndexByIdentity: ReadonlyMap<string, number> = new Map<string, number>();
|
|
975
|
-
if (needsCandidateIdentityFallback) {
|
|
976
|
-
if (candidateDomain !== undefined) {
|
|
977
|
-
// The persistent candidate domain is the only owner that remains
|
|
978
|
-
// correct after projection removals compact the candidate array. A
|
|
979
|
-
// projection slot may still carry the old snapshot candidateIndex;
|
|
980
|
-
// never let that stale producer hint override the domain join.
|
|
981
|
-
candidateIndexByIdentity = candidateDomain.indexByIdentity;
|
|
982
|
-
} else {
|
|
983
|
-
const fallback = new Map<string, number>();
|
|
984
|
-
for (let index = 0; index < (input.frame.candidateRenderables?.length ?? 0); index += 1) {
|
|
985
|
-
const candidate = input.frame.candidateRenderables?.[index];
|
|
986
|
-
if (candidate !== undefined) {
|
|
987
|
-
fallback.set(`${candidate.worldId}:${candidate.entityKey}`, index);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
candidateIndexByIdentity = fallback;
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
const candidatesBySlot = new Map<number, CpuVisibilityCandidate>();
|
|
994
|
-
const shadowCasterCandidateIndices =
|
|
995
|
-
input.frame.candidateDomain?.membership.shadowCasterCandidateIndices ??
|
|
996
|
-
input.frame.candidateDispatchMembership?.shadowCasterCandidateIndices;
|
|
997
|
-
const shadowCasterSlotIndices =
|
|
998
|
-
shadowCasterCandidateIndices === undefined ? undefined : new Set<number>();
|
|
999
|
-
for (const slot of input.scene.slots) {
|
|
1000
|
-
const batch = batchBySlot.get(slot.slot);
|
|
1001
|
-
const worldAabb =
|
|
1002
|
-
slot.fact.bounds.status === 'present' ? slot.fact.bounds.worldAabb : undefined;
|
|
1003
|
-
const candidateIndex =
|
|
1004
|
-
candidateDomain === undefined
|
|
1005
|
-
? (slot.snapshot.candidateIndex ??
|
|
1006
|
-
candidateIndexByIdentity.get(`${slot.worldId}:${slot.entityKey}`))
|
|
1007
|
-
: candidateIndexByIdentity.get(`${slot.worldId}:${slot.entityKey}`);
|
|
1008
|
-
const dispatchShadowCaster =
|
|
1009
|
-
shadowCasterCandidateIndices === undefined ||
|
|
1010
|
-
candidateIndex === undefined ||
|
|
1011
|
-
shadowCasterCandidateIndices.has(candidateIndex);
|
|
1012
|
-
if (
|
|
1013
|
-
dispatchShadowCaster &&
|
|
1014
|
-
slot.fact.casterEligibility !== 'ineligible' &&
|
|
1015
|
-
shadowCasterSlotIndices !== undefined
|
|
1016
|
-
) {
|
|
1017
|
-
shadowCasterSlotIndices.add(slot.slot);
|
|
1018
|
-
}
|
|
1019
|
-
candidatesBySlot.set(slot.slot, {
|
|
1020
|
-
stableId: slot.slot,
|
|
1021
|
-
generation: slot.generation,
|
|
1022
|
-
candidateIndex,
|
|
1023
|
-
worldAabb,
|
|
1024
|
-
// Unknown authoring facts remain conservative. Only an explicit
|
|
1025
|
-
// ineligible fact may remove a candidate from a shadow view.
|
|
1026
|
-
casterEligible: slot.fact.casterEligibility !== 'ineligible' && dispatchShadowCaster,
|
|
1027
|
-
batchId: batch?.batchId,
|
|
1028
|
-
instanceOrdinal: batch?.instanceOrdinal,
|
|
1029
|
-
});
|
|
1030
|
-
}
|
|
1031
|
-
this.shadowCasterSlotIndices =
|
|
1032
|
-
shadowCasterSlotIndices === undefined
|
|
1033
|
-
? undefined
|
|
1034
|
-
: (Object.freeze(shadowCasterSlotIndices) as ReadonlySet<number>);
|
|
1035
|
-
const candidatesByView = new Map<string, readonly CpuVisibilityCandidate[]>();
|
|
1036
|
-
const candidateUnion = new Map<number, CpuVisibilityCandidate>();
|
|
1037
|
-
for (const view of descriptors) {
|
|
1038
|
-
const hits =
|
|
1039
|
-
view.broadphaseWorldAabb === undefined || input.scene.projection === undefined
|
|
1040
|
-
? input.scene.slots
|
|
1041
|
-
: input.scene.projection.querySpatialIndex(view.broadphaseWorldAabb).hits;
|
|
1042
|
-
const domain: CpuVisibilityCandidate[] = [];
|
|
1043
|
-
for (const hit of hits) {
|
|
1044
|
-
const candidate = candidatesBySlot.get(hit.slot);
|
|
1045
|
-
if (candidate === undefined) continue;
|
|
1046
|
-
domain.push(candidate);
|
|
1047
|
-
candidateUnion.set(candidate.stableId, candidate);
|
|
1048
|
-
}
|
|
1049
|
-
candidatesByView.set(view.viewId, Object.freeze(domain));
|
|
1050
|
-
}
|
|
1051
|
-
const candidates = [...candidateUnion.values()];
|
|
1052
|
-
// Main visibility is independent from the GPU batch domain. Keep its
|
|
1053
|
-
// compact array large enough for non-GPU renderables in the broadphase
|
|
1054
|
-
// domain, otherwise a valid CPU-only object would be reported as an
|
|
1055
|
-
// artificial visibility overflow.
|
|
1056
|
-
const capacity = Math.max(1, input.scene.plan.visibleCapacity, candidates.length);
|
|
1057
|
-
const capacityByView = new Map(descriptors.map((view) => [view.viewId, capacity] as const));
|
|
1058
|
-
this.visibilityViews = descriptors;
|
|
1059
|
-
this.cpuVisibility = executeCpuMultiViewVisibility({
|
|
1060
|
-
views: descriptors,
|
|
1061
|
-
candidates,
|
|
1062
|
-
candidatesByView,
|
|
1063
|
-
capacityByView,
|
|
1064
|
-
capacityByBatch,
|
|
1065
|
-
});
|
|
1066
|
-
return this.cpuVisibility;
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
424
|
prepare(input: {
|
|
1070
425
|
readonly scene: PersistentGpuDrivenState | undefined;
|
|
1071
426
|
readonly camera: CameraSnapshot;
|
|
1072
427
|
readonly meshes: ReadonlyMap<number, MeshGpuHandles>;
|
|
1073
428
|
readonly viewBindGroupLayout: BindGroupLayout;
|
|
1074
|
-
readonly materialBindGroupLayout?: BindGroupLayout;
|
|
1075
429
|
readonly meshResidencyEpoch: number;
|
|
1076
430
|
readonly hdrp: boolean;
|
|
1077
431
|
}): Result<PreparedGpuDrivenFrame | undefined, RhiError> {
|
|
@@ -1080,11 +434,14 @@ export class GpuDrivenProduction {
|
|
|
1080
434
|
this.batchBindGroupCreates = 0;
|
|
1081
435
|
this.validatedGpuOwnedRows = 0;
|
|
1082
436
|
this.cpuFallbackDrawItems = 0;
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
this.
|
|
437
|
+
if (
|
|
438
|
+
input.hdrp ||
|
|
439
|
+
input.scene === undefined ||
|
|
440
|
+
!this.device.caps.compute ||
|
|
441
|
+
!this.device.caps.storageBuffer ||
|
|
442
|
+
!this.device.caps.indirectDrawing
|
|
443
|
+
) {
|
|
444
|
+
this.gpuOwnedEntityCount = 0;
|
|
1088
445
|
return ok(undefined);
|
|
1089
446
|
}
|
|
1090
447
|
const scene = input.scene;
|
|
@@ -1103,41 +460,14 @@ export class GpuDrivenProduction {
|
|
|
1103
460
|
this.gpuOwnedSnapshotsMaterialized = scene.slots.length;
|
|
1104
461
|
this.filteredPlanBuilds = 1;
|
|
1105
462
|
}
|
|
1106
|
-
this.
|
|
1107
|
-
|
|
1108
|
-
filtered.shadowPlan,
|
|
1109
|
-
this.shadowCasterSlotIndices,
|
|
1110
|
-
);
|
|
1111
|
-
this.shadowSubmission = shadowSubmission;
|
|
1112
|
-
if (
|
|
1113
|
-
input.hdrp ||
|
|
1114
|
-
!this.device.caps.compute ||
|
|
1115
|
-
!this.device.caps.storageBuffer ||
|
|
1116
|
-
!this.device.caps.indirectDrawing ||
|
|
1117
|
-
(filtered.batches.length === 0 && shadowSubmission.batches.length === 0)
|
|
1118
|
-
) {
|
|
1119
|
-
if (shadowSubmission.candidateCount > 0) {
|
|
1120
|
-
this.addFault({
|
|
1121
|
-
code: 'gpu-capability-unavailable',
|
|
1122
|
-
viewId: 'all',
|
|
1123
|
-
revision: shadowSubmission.revision,
|
|
1124
|
-
fallback: 'cpu-batch-contract',
|
|
1125
|
-
detail: input.hdrp
|
|
1126
|
-
? 'HDRP production raster does not expose the rigid shadow capability lane'
|
|
1127
|
-
: 'compute, storage-buffer, indirect-drawing, or forward batch capability is unavailable',
|
|
1128
|
-
});
|
|
1129
|
-
}
|
|
1130
|
-
return ok(undefined);
|
|
1131
|
-
}
|
|
463
|
+
this.gpuOwnedEntityCount = filtered.entityKeys.size;
|
|
464
|
+
if (filtered.batches.length === 0) return ok(undefined);
|
|
1132
465
|
if (this.view === undefined) {
|
|
1133
466
|
const created = GpuDrivenView.create({
|
|
1134
467
|
device: this.device,
|
|
1135
468
|
shaderModuleFactory: this.shaderModuleFactory,
|
|
1136
469
|
});
|
|
1137
|
-
if (!created.ok)
|
|
1138
|
-
this.addRhiFault(created.error, 'all', filtered.plan.revision);
|
|
1139
|
-
return created;
|
|
1140
|
-
}
|
|
470
|
+
if (!created.ok) return created;
|
|
1141
471
|
this.view = created.value;
|
|
1142
472
|
}
|
|
1143
473
|
if (this.raster === undefined) {
|
|
@@ -1146,35 +476,11 @@ export class GpuDrivenProduction {
|
|
|
1146
476
|
shaderModuleFactory: this.shaderModuleFactory,
|
|
1147
477
|
viewBindGroupLayout: input.viewBindGroupLayout,
|
|
1148
478
|
});
|
|
1149
|
-
if (!created.ok)
|
|
1150
|
-
this.addRhiFault(created.error, 'all', filtered.plan.revision);
|
|
1151
|
-
return created;
|
|
1152
|
-
}
|
|
479
|
+
if (!created.ok) return created;
|
|
1153
480
|
this.raster = created.value;
|
|
1154
481
|
}
|
|
1155
|
-
if (this.shadowRaster === undefined && input.materialBindGroupLayout !== undefined) {
|
|
1156
|
-
const created = GpuDrivenShadowRaster.create({
|
|
1157
|
-
device: this.device,
|
|
1158
|
-
shaderModuleFactory: this.shaderModuleFactory,
|
|
1159
|
-
viewBindGroupLayout: input.viewBindGroupLayout,
|
|
1160
|
-
materialBindGroupLayout: input.materialBindGroupLayout,
|
|
1161
|
-
});
|
|
1162
|
-
if (!created.ok) {
|
|
1163
|
-
this.addRhiFault(created.error, 'all', shadowSubmission.revision);
|
|
1164
|
-
} else {
|
|
1165
|
-
this.shadowRaster = created.value;
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
482
|
const updated = this.view.update(filtered.plan, scene.scene, activeFrustum(input.camera));
|
|
1169
|
-
if (!updated.ok)
|
|
1170
|
-
this.addRhiFault(updated.error, 'main', filtered.plan.revision);
|
|
1171
|
-
return updated;
|
|
1172
|
-
}
|
|
1173
|
-
const shadowPrepared = this.prepareShadowViews(scene, shadowSubmission, input.meshes);
|
|
1174
|
-
if (!shadowPrepared.ok) {
|
|
1175
|
-
this.addRhiFault(shadowPrepared.error, 'all', shadowSubmission.revision);
|
|
1176
|
-
return shadowPrepared;
|
|
1177
|
-
}
|
|
483
|
+
if (!updated.ok) return updated;
|
|
1178
484
|
const view = this.view;
|
|
1179
485
|
const raster = this.raster;
|
|
1180
486
|
const sceneIdentity = this.sceneIdentity(scene.scene);
|
|
@@ -1204,7 +510,7 @@ export class GpuDrivenProduction {
|
|
|
1204
510
|
mesh.vboBytes,
|
|
1205
511
|
mesh.iboBytes,
|
|
1206
512
|
mesh.indexFormat,
|
|
1207
|
-
mesh.
|
|
513
|
+
mesh.uvSetCount,
|
|
1208
514
|
]),
|
|
1209
515
|
capacities: [
|
|
1210
516
|
viewInspection.candidateCapacity,
|
|
@@ -1222,11 +528,9 @@ export class GpuDrivenProduction {
|
|
|
1222
528
|
}
|
|
1223
529
|
return ok({
|
|
1224
530
|
topologySignature: signature,
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
[...filtered.forwardItemKeys].every((key) => filtered.itemKeys.has(key)),
|
|
1229
|
-
shadowSubmission,
|
|
531
|
+
entityKeys: filtered.entityKeys,
|
|
532
|
+
ownsAllRenderables: filtered.entityKeys.size === scene.slots.length,
|
|
533
|
+
_commitResourceReplacement: () => view._commitResourceReplacement(),
|
|
1230
534
|
project: (graph, format, sampleCount) => {
|
|
1231
535
|
const outputs = view.addPasses(graph);
|
|
1232
536
|
if (!outputs.ok) return outputs;
|
|
@@ -1279,7 +583,7 @@ export class GpuDrivenProduction {
|
|
|
1279
583
|
const pipeline = raster.pipeline(
|
|
1280
584
|
format,
|
|
1281
585
|
sampleCount,
|
|
1282
|
-
prepared.mesh.
|
|
586
|
+
48 + (prepared.mesh.uvSetCount - 1) * 8,
|
|
1283
587
|
prepared.batch.key.topology,
|
|
1284
588
|
prepared.batch.key.drawKind === 'indexed' &&
|
|
1285
589
|
(prepared.batch.key.topology === 'line-strip' ||
|
|
@@ -1299,68 +603,8 @@ export class GpuDrivenProduction {
|
|
|
1299
603
|
bindings: bindings.value,
|
|
1300
604
|
});
|
|
1301
605
|
}
|
|
1302
|
-
const shadow: RenderPipelineGpuDrivenShadowProjection[] = [];
|
|
1303
|
-
const shadowRaster = this.shadowRaster;
|
|
1304
|
-
if (shadowRaster !== undefined) {
|
|
1305
|
-
for (const prepared of this.preparedShadowViews) {
|
|
1306
|
-
const shadowOutputs = prepared.view.addPasses(graph, prepared.graphLabel);
|
|
1307
|
-
if (!shadowOutputs.ok) return shadowOutputs;
|
|
1308
|
-
const shadowAccesses: GraphAccess[] = [
|
|
1309
|
-
{ resource: shadowOutputs.value.primitive, usage: 'storage-read' },
|
|
1310
|
-
{ resource: shadowOutputs.value.instance, usage: 'storage-read' },
|
|
1311
|
-
{ resource: shadowOutputs.value.transform, usage: 'storage-read' },
|
|
1312
|
-
{ resource: shadowOutputs.value.visible, usage: 'storage-read' },
|
|
1313
|
-
{ resource: shadowOutputs.value.indirect, usage: 'indirect-read' },
|
|
1314
|
-
];
|
|
1315
|
-
const meshBuffers = new Map<
|
|
1316
|
-
number,
|
|
1317
|
-
{ readonly vertex: GraphBuffer; readonly index?: GraphBuffer }
|
|
1318
|
-
>();
|
|
1319
|
-
for (const batch of prepared.batches) {
|
|
1320
|
-
let buffers = meshBuffers.get(batch.batch.key.assetHandle);
|
|
1321
|
-
if (buffers === undefined) {
|
|
1322
|
-
const vertex = graph.importBuffer(
|
|
1323
|
-
`${prepared.graphLabel}.mesh.${batch.batch.key.assetHandle}.vertex`,
|
|
1324
|
-
{
|
|
1325
|
-
size: batch.mesh.vboBytes,
|
|
1326
|
-
usage: GPU_BUFFER_USAGE_VERTEX | GPU_BUFFER_USAGE_COPY_DST,
|
|
1327
|
-
},
|
|
1328
|
-
() => batch.mesh.vertexBuffer.handle,
|
|
1329
|
-
);
|
|
1330
|
-
if (!vertex.ok) return vertex;
|
|
1331
|
-
let index: GraphBuffer | undefined;
|
|
1332
|
-
if (batch.mesh.indexBuffer !== null) {
|
|
1333
|
-
const imported = graph.importBuffer(
|
|
1334
|
-
`${prepared.graphLabel}.mesh.${batch.batch.key.assetHandle}.index`,
|
|
1335
|
-
{
|
|
1336
|
-
size: batch.mesh.iboBytes,
|
|
1337
|
-
usage: GPU_BUFFER_USAGE_INDEX | GPU_BUFFER_USAGE_COPY_DST,
|
|
1338
|
-
},
|
|
1339
|
-
() => batch.mesh.indexBuffer?.handle as import('@forgeax/engine-rhi').Buffer,
|
|
1340
|
-
);
|
|
1341
|
-
if (!imported.ok) return imported;
|
|
1342
|
-
index = imported.value;
|
|
1343
|
-
}
|
|
1344
|
-
buffers = { vertex: vertex.value, ...(index === undefined ? {} : { index }) };
|
|
1345
|
-
meshBuffers.set(batch.batch.key.assetHandle, buffers);
|
|
1346
|
-
shadowAccesses.push({ resource: buffers.vertex, usage: 'vertex-read' });
|
|
1347
|
-
if (buffers.index !== undefined) {
|
|
1348
|
-
shadowAccesses.push({ resource: buffers.index, usage: 'index-read' });
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
shadow.push({
|
|
1353
|
-
cascadeIndex: prepared.cascadeIndex,
|
|
1354
|
-
accesses: Object.freeze(shadowAccesses),
|
|
1355
|
-
batchCount: prepared.batches.length,
|
|
1356
|
-
encode: (pass, resources) =>
|
|
1357
|
-
shadowRaster.encode(prepared, resources, shadowOutputs.value, pass),
|
|
1358
|
-
});
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
606
|
return ok({
|
|
1362
607
|
accesses,
|
|
1363
|
-
shadow: Object.freeze(shadow),
|
|
1364
608
|
encode: (viewBindGroup, pass, resources: GraphResourceResolver) => {
|
|
1365
609
|
pass.setBindGroup(0, viewBindGroup);
|
|
1366
610
|
let currentPipeline: RenderPipeline | undefined;
|
|
@@ -1398,238 +642,12 @@ export class GpuDrivenProduction {
|
|
|
1398
642
|
});
|
|
1399
643
|
}
|
|
1400
644
|
|
|
1401
|
-
/**
|
|
1402
|
-
* Intersect the four-view visibility result with the shared ShadowCaster
|
|
1403
|
-
* topology. This is the only production candidate-to-submission join; CPU
|
|
1404
|
-
* fallback devices consume the same immutable plans as indirect-capable
|
|
1405
|
-
* devices.
|
|
1406
|
-
*/
|
|
1407
|
-
multiViewSubmissions(): readonly MultiViewProductionSubmission[] {
|
|
1408
|
-
if (this.cpuVisibility === undefined || this.shadowSubmission === undefined) {
|
|
1409
|
-
return [];
|
|
1410
|
-
}
|
|
1411
|
-
const shadowSubmission = this.shadowSubmission;
|
|
1412
|
-
return Object.freeze(
|
|
1413
|
-
this.cpuVisibility.views.map((view) => {
|
|
1414
|
-
const candidateIndexByStableId = new Map<number, number>();
|
|
1415
|
-
for (const candidate of view.compactVisible) {
|
|
1416
|
-
if (candidate.candidateIndex !== undefined) {
|
|
1417
|
-
candidateIndexByStableId.set(candidate.stableId, candidate.candidateIndex);
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
const plan = this.shadowSubmissionForView(shadowSubmission, view);
|
|
1421
|
-
const candidateIndices = new Set<number>();
|
|
1422
|
-
for (const batch of plan.batches) {
|
|
1423
|
-
for (const candidate of batch.candidates) {
|
|
1424
|
-
const candidateIndex = candidateIndexByStableId.get(candidate.primitiveIndex);
|
|
1425
|
-
if (candidateIndex !== undefined) candidateIndices.add(candidateIndex);
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
return Object.freeze({
|
|
1429
|
-
source: 'multi-view-indirect' as const,
|
|
1430
|
-
viewId: view.viewId,
|
|
1431
|
-
kind: view.kind,
|
|
1432
|
-
cascadeIndex: view.cascadeIndex,
|
|
1433
|
-
volumeRevision: view.volumeRevision,
|
|
1434
|
-
spatialIndexRevision: view.spatialIndexRevision,
|
|
1435
|
-
overflow: view.overflow,
|
|
1436
|
-
plan,
|
|
1437
|
-
candidateIndexByStableId,
|
|
1438
|
-
candidateIndices,
|
|
1439
|
-
faults: Object.freeze(
|
|
1440
|
-
this.faults.filter((fault) => fault.viewId === 'all' || fault.viewId === view.viewId),
|
|
1441
|
-
),
|
|
1442
|
-
});
|
|
1443
|
-
}),
|
|
1444
|
-
);
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
private prepareShadowViews(
|
|
1448
|
-
scene: PersistentGpuDrivenState,
|
|
1449
|
-
shadowSource: SubmissionPlan,
|
|
1450
|
-
meshes: ReadonlyMap<number, MeshGpuHandles>,
|
|
1451
|
-
): Result<void, RhiError> {
|
|
1452
|
-
this.preparedShadowViews = [];
|
|
1453
|
-
if (this.shadowRaster === undefined || this.cpuVisibility === undefined) return ok(undefined);
|
|
1454
|
-
const slotByPrimitive = new Map(scene.slots.map((slot) => [slot.slot, slot] as const));
|
|
1455
|
-
const descriptorByView = new Map(
|
|
1456
|
-
this.visibilityViews.map((view) => [view.viewId, view] as const),
|
|
1457
|
-
);
|
|
1458
|
-
const prepared: PreparedShadowView[] = [];
|
|
1459
|
-
for (const viewResult of this.cpuVisibility.views) {
|
|
1460
|
-
if (viewResult.kind !== 'cascade' || viewResult.cascadeIndex === undefined) continue;
|
|
1461
|
-
const descriptor = descriptorByView.get(viewResult.viewId);
|
|
1462
|
-
if (
|
|
1463
|
-
descriptor === undefined ||
|
|
1464
|
-
descriptor.lightViewProj === undefined ||
|
|
1465
|
-
descriptor.planes.length < 24 ||
|
|
1466
|
-
viewResult.overflow
|
|
1467
|
-
) {
|
|
1468
|
-
if (viewResult.overflow) {
|
|
1469
|
-
this.addFault({
|
|
1470
|
-
code: 'visibility-overflow',
|
|
1471
|
-
viewId: viewResult.viewId,
|
|
1472
|
-
revision: shadowSource.revision,
|
|
1473
|
-
fallback: 'cpu-batch-contract',
|
|
1474
|
-
detail:
|
|
1475
|
-
'compact visibility capacity was exceeded; the complete CPU batch contract remains authoritative',
|
|
1476
|
-
});
|
|
1477
|
-
} else if (descriptor === undefined || descriptor.lightViewProj === undefined) {
|
|
1478
|
-
this.addFault({
|
|
1479
|
-
code: 'gpu-resource-failed',
|
|
1480
|
-
viewId: viewResult.viewId,
|
|
1481
|
-
revision: shadowSource.revision,
|
|
1482
|
-
fallback: 'cpu-batch-contract',
|
|
1483
|
-
detail: 'cascade volume did not publish a canonical raster matrix',
|
|
1484
|
-
});
|
|
1485
|
-
}
|
|
1486
|
-
continue;
|
|
1487
|
-
}
|
|
1488
|
-
const plan = this.shadowSubmissionForView(shadowSource, viewResult);
|
|
1489
|
-
if (plan.batches.length === 0) continue;
|
|
1490
|
-
let gpuSafe = true;
|
|
1491
|
-
for (const batch of plan.batches) {
|
|
1492
|
-
const mesh = meshes.get(batch.key.assetHandle);
|
|
1493
|
-
if (
|
|
1494
|
-
batch.key.alphaTest ||
|
|
1495
|
-
(batch.key.materialClass !== 'forgeax::default-unlit' &&
|
|
1496
|
-
batch.key.materialClass !== 'forgeax::default-standard-pbr') ||
|
|
1497
|
-
mesh === undefined ||
|
|
1498
|
-
!supportsRigidGpuDrivenProjection(mesh) ||
|
|
1499
|
-
(batch.key.topology !== 'triangle-list' && batch.key.topology !== 'triangle-strip') ||
|
|
1500
|
-
(batch.key.drawKind === 'indexed' && (!mesh.indexed || mesh.indexBuffer === null)) ||
|
|
1501
|
-
(batch.key.drawKind === 'non-indexed' && mesh.indexed)
|
|
1502
|
-
) {
|
|
1503
|
-
gpuSafe = false;
|
|
1504
|
-
break;
|
|
1505
|
-
}
|
|
1506
|
-
for (const candidate of batch.candidates) {
|
|
1507
|
-
const slot = slotByPrimitive.get(candidate.primitiveIndex);
|
|
1508
|
-
if (
|
|
1509
|
-
slot === undefined ||
|
|
1510
|
-
slot.fact.bounds.status !== 'present' ||
|
|
1511
|
-
slot.snapshot.gpuDrivenDraws === undefined
|
|
1512
|
-
) {
|
|
1513
|
-
gpuSafe = false;
|
|
1514
|
-
break;
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
if (!gpuSafe) break;
|
|
1518
|
-
}
|
|
1519
|
-
if (!gpuSafe) {
|
|
1520
|
-
this.addFault({
|
|
1521
|
-
code: 'gpu-scene-fact-unavailable',
|
|
1522
|
-
viewId: viewResult.viewId,
|
|
1523
|
-
revision: shadowSource.revision,
|
|
1524
|
-
fallback: 'cpu-batch-contract',
|
|
1525
|
-
detail:
|
|
1526
|
-
'one or more casters lack bounded GPU Scene facts required by the exact shadow cull',
|
|
1527
|
-
});
|
|
1528
|
-
continue;
|
|
1529
|
-
}
|
|
1530
|
-
let view = this.shadowViews.get(viewResult.cascadeIndex);
|
|
1531
|
-
if (view === undefined) {
|
|
1532
|
-
const created = GpuDrivenView.create({
|
|
1533
|
-
device: this.device,
|
|
1534
|
-
shaderModuleFactory: this.shaderModuleFactory,
|
|
1535
|
-
});
|
|
1536
|
-
if (!created.ok) {
|
|
1537
|
-
this.addRhiFault(created.error, viewResult.viewId, shadowSource.revision);
|
|
1538
|
-
continue;
|
|
1539
|
-
}
|
|
1540
|
-
view = created.value;
|
|
1541
|
-
this.shadowViews.set(viewResult.cascadeIndex, view);
|
|
1542
|
-
}
|
|
1543
|
-
const updated = view.update(plan, scene.scene, descriptor.planes);
|
|
1544
|
-
if (!updated.ok) {
|
|
1545
|
-
this.addRhiFault(updated.error, viewResult.viewId, shadowSource.revision);
|
|
1546
|
-
continue;
|
|
1547
|
-
}
|
|
1548
|
-
const shadowView = this.shadowRaster.prepareView({
|
|
1549
|
-
cascadeIndex: viewResult.cascadeIndex,
|
|
1550
|
-
scene: scene.scene,
|
|
1551
|
-
view,
|
|
1552
|
-
plan,
|
|
1553
|
-
lightViewProj: descriptor.lightViewProj,
|
|
1554
|
-
meshes,
|
|
1555
|
-
graphLabel: `gpu-driven.shadow.cascade-${viewResult.cascadeIndex}`,
|
|
1556
|
-
});
|
|
1557
|
-
if (!shadowView.ok) {
|
|
1558
|
-
this.addRhiFault(shadowView.error, viewResult.viewId, shadowSource.revision);
|
|
1559
|
-
continue;
|
|
1560
|
-
}
|
|
1561
|
-
if (shadowView.value !== undefined) prepared.push(shadowView.value);
|
|
1562
|
-
}
|
|
1563
|
-
this.preparedShadowViews = Object.freeze(prepared);
|
|
1564
|
-
return ok(undefined);
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
private shadowSubmissionForView(
|
|
1568
|
-
shadowSubmission: SubmissionPlan,
|
|
1569
|
-
view: CpuMultiViewVisibilityResult['views'][number],
|
|
1570
|
-
): SubmissionPlan {
|
|
1571
|
-
const cached = this.shadowPlanCache.get(view.viewId);
|
|
1572
|
-
const stableIds = view.compactVisible.map((candidate) => candidate.stableId);
|
|
1573
|
-
const generations = view.compactVisible.map((candidate) => candidate.generation);
|
|
1574
|
-
if (
|
|
1575
|
-
cached !== undefined &&
|
|
1576
|
-
cached.source === shadowSubmission &&
|
|
1577
|
-
sameNumberArray(cached.stableIds, stableIds) &&
|
|
1578
|
-
sameNumberArray(cached.generations, generations)
|
|
1579
|
-
) {
|
|
1580
|
-
return cached.plan;
|
|
1581
|
-
}
|
|
1582
|
-
let reverse = this.shadowCandidateMembership;
|
|
1583
|
-
if (reverse?.source !== shadowSubmission) {
|
|
1584
|
-
reverse = buildSubmissionCandidateMembership(shadowSubmission);
|
|
1585
|
-
this.shadowCandidateMembership = reverse;
|
|
1586
|
-
}
|
|
1587
|
-
const candidatesByBatch = new Map<number, GpuDrivenCandidate[]>();
|
|
1588
|
-
// compactVisible is stable-id ordered because the CPU visibility owner
|
|
1589
|
-
// sorts its candidate domain once. Appending each slot's source-order
|
|
1590
|
-
// candidates therefore preserves the old deterministic order while
|
|
1591
|
-
// changing the join from O(all shadow candidates per cascade) to
|
|
1592
|
-
// O(selected candidates).
|
|
1593
|
-
for (const visible of view.compactVisible) {
|
|
1594
|
-
const entries = reverse.byPrimitiveIndex.get(visible.stableId);
|
|
1595
|
-
if (entries === undefined) continue;
|
|
1596
|
-
for (const entry of entries) {
|
|
1597
|
-
if (entry.candidate.generation !== visible.generation) continue;
|
|
1598
|
-
const candidates = candidatesByBatch.get(entry.batchId) ?? [];
|
|
1599
|
-
candidates.push(entry.candidate);
|
|
1600
|
-
candidatesByBatch.set(entry.batchId, candidates);
|
|
1601
|
-
}
|
|
1602
|
-
}
|
|
1603
|
-
const frozenCandidatesByBatch = new Map<number, readonly GpuDrivenCandidate[]>();
|
|
1604
|
-
for (const [batchId, candidates] of candidatesByBatch) {
|
|
1605
|
-
frozenCandidatesByBatch.set(batchId, Object.freeze(candidates));
|
|
1606
|
-
}
|
|
1607
|
-
const plan = buildBatchAlignedSubmission(shadowSubmission, frozenCandidatesByBatch);
|
|
1608
|
-
this.shadowPlanCache.set(view.viewId, {
|
|
1609
|
-
source: shadowSubmission,
|
|
1610
|
-
stableIds: Object.freeze(stableIds),
|
|
1611
|
-
generations: Object.freeze(generations),
|
|
1612
|
-
plan,
|
|
1613
|
-
});
|
|
1614
|
-
return plan;
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
645
|
dispose(): void {
|
|
1618
646
|
this.view?.dispose();
|
|
1619
|
-
for (const view of this.shadowViews.values()) view.dispose();
|
|
1620
|
-
this.shadowViews.clear();
|
|
1621
|
-
this.shadowRaster?.dispose();
|
|
1622
647
|
this.view = undefined;
|
|
1623
648
|
this.raster = undefined;
|
|
1624
|
-
this.shadowRaster = undefined;
|
|
1625
|
-
this.preparedShadowViews = [];
|
|
1626
649
|
this.filteredCache = undefined;
|
|
1627
650
|
this.signatureCache = undefined;
|
|
1628
|
-
this.cpuVisibility = undefined;
|
|
1629
|
-
this.shadowCasterSlotIndices = undefined;
|
|
1630
|
-
this.shadowSubmission = undefined;
|
|
1631
|
-
this.shadowPlanCache.clear();
|
|
1632
|
-
this.shadowCandidateMembership = undefined;
|
|
1633
651
|
}
|
|
1634
652
|
|
|
1635
653
|
inspect(): GpuDrivenProductionInspection {
|
|
@@ -1637,7 +655,7 @@ export class GpuDrivenProduction {
|
|
|
1637
655
|
return {
|
|
1638
656
|
gpuOwnedSnapshotsMaterialized: this.gpuOwnedSnapshotsMaterialized,
|
|
1639
657
|
filteredPlanBuilds: this.filteredPlanBuilds,
|
|
1640
|
-
|
|
658
|
+
gpuOwnedEntityCount: this.gpuOwnedEntityCount,
|
|
1641
659
|
candidateUploadBytes: view?.candidateUploadBytes ?? 0,
|
|
1642
660
|
batchUploadBytes: view?.batchUploadBytes ?? 0,
|
|
1643
661
|
viewConstantsUploadBytes: view?.viewConstantsUploadBytes ?? 0,
|
|
@@ -1646,37 +664,19 @@ export class GpuDrivenProduction {
|
|
|
1646
664
|
topologyRevision: view?.topologyRevision,
|
|
1647
665
|
validatedGpuOwnedRows: this.validatedGpuOwnedRows,
|
|
1648
666
|
cpuFallbackDrawItems: this.cpuFallbackDrawItems,
|
|
1649
|
-
cpuVisibility: this.cpuVisibility,
|
|
1650
|
-
shadowBatchCount: this.shadowSubmission?.batches.length ?? 0,
|
|
1651
|
-
shadowCandidateCount: this.shadowSubmission?.candidateCount ?? 0,
|
|
1652
|
-
shadowDrawCount: this.preparedShadowViews.reduce(
|
|
1653
|
-
(total, prepared) => total + prepared.batches.length,
|
|
1654
|
-
0,
|
|
1655
|
-
),
|
|
1656
|
-
faults: this.faults,
|
|
1657
667
|
};
|
|
1658
668
|
}
|
|
1659
669
|
|
|
1660
670
|
recordCpuValidation(
|
|
1661
671
|
validated: readonly { readonly source: RenderableSnapshot }[],
|
|
1662
|
-
gpuOwned: ReadonlySet<
|
|
672
|
+
gpuOwned: ReadonlySet<number>,
|
|
1663
673
|
): void {
|
|
1664
|
-
|
|
674
|
+
this.cpuFallbackDrawItems = validated.length;
|
|
675
|
+
let gpuOwnedRows = 0;
|
|
1665
676
|
for (const row of validated) {
|
|
1666
|
-
|
|
1667
|
-
const key = rasterItemKey(
|
|
1668
|
-
row.source.worldId,
|
|
1669
|
-
row.source.entityKey,
|
|
1670
|
-
draw.submeshIndex,
|
|
1671
|
-
draw.passIndex,
|
|
1672
|
-
);
|
|
1673
|
-
if (!gpuOwned.has(key)) cpuFallbackItems += 1;
|
|
1674
|
-
}
|
|
677
|
+
if (gpuOwned.has(worldEntityKey(row.source.worldId, row.source.entityKey))) gpuOwnedRows += 1;
|
|
1675
678
|
}
|
|
1676
|
-
this.
|
|
1677
|
-
// Validation remains a renderable/mesh-residency phase. Ownership is
|
|
1678
|
-
// published only for item keys, so no validated row is GPU-owned.
|
|
1679
|
-
this.validatedGpuOwnedRows = 0;
|
|
679
|
+
this.validatedGpuOwnedRows = gpuOwnedRows;
|
|
1680
680
|
}
|
|
1681
681
|
|
|
1682
682
|
private sceneIdentity(scene: object): number {
|
|
@@ -1687,19 +687,4 @@ export class GpuDrivenProduction {
|
|
|
1687
687
|
this.sceneIdentities.set(scene, identity);
|
|
1688
688
|
return identity;
|
|
1689
689
|
}
|
|
1690
|
-
|
|
1691
|
-
private addFault(fault: GpuDrivenVisibilityFault): void {
|
|
1692
|
-
this.faults = Object.freeze([...this.faults, Object.freeze(fault)]);
|
|
1693
|
-
}
|
|
1694
|
-
|
|
1695
|
-
private addRhiFault(error: RhiError, viewId: string, revision: number): void {
|
|
1696
|
-
const requiresRecovery = error.code === 'device-lost' || error.code === 'oom';
|
|
1697
|
-
this.addFault({
|
|
1698
|
-
code: requiresRecovery ? 'device-recovery-required' : 'gpu-resource-failed',
|
|
1699
|
-
viewId,
|
|
1700
|
-
revision,
|
|
1701
|
-
fallback: requiresRecovery ? 'scene-rebuild' : 'cpu-batch-contract',
|
|
1702
|
-
detail: `${error.code}: ${error.message}`,
|
|
1703
|
-
});
|
|
1704
|
-
}
|
|
1705
690
|
}
|