@forgeax/engine-render 0.1.27 → 0.1.29
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 +842 -124
- package/dist/assembly/atmosphere-shader-prewarm.d.ts +6 -0
- package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/dynamic-geometry-host.d.ts +52 -0
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -0
- package/dist/assembly/dynamic-geometry-runtime.d.ts +20 -0
- package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +3 -1
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/gpu-driven-owner.d.ts +10 -0
- package/dist/assembly/gpu-driven-owner.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +19 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +7 -0
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material-shader-policy.d.ts +3 -1
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/recovery/failure-location.d.ts +12 -0
- package/dist/assembly/recovery/failure-location.d.ts.map +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts +6 -4
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/renderer-feature-inspection.d.ts +5 -0
- package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -0
- package/dist/assembly/renderer-frame-transaction.d.ts +19 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-helpers.d.ts +3 -0
- package/dist/assembly/renderer-helpers.d.ts.map +1 -1
- package/dist/assembly/renderer-inspection.d.ts +4 -0
- package/dist/assembly/renderer-inspection.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +6 -0
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
- package/dist/assembly/skin-palette-owner.d.ts +8 -0
- package/dist/assembly/skin-palette-owner.d.ts.map +1 -0
- package/dist/assembly/ssr-shader-prewarm.d.ts +6 -0
- package/dist/assembly/ssr-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/webgpu-device-loss.d.ts +15 -0
- package/dist/assembly/webgpu-device-loss.d.ts.map +1 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts +38 -0
- package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready-mipmap.d.ts +11 -0
- package/dist/assembly/webgpu-ready-mipmap.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +7 -3
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts +10 -0
- package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-contract.d.ts +62 -0
- package/dist/assembly/webgpu-renderer-contract.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-guards.d.ts +9 -0
- package/dist/assembly/webgpu-renderer-guards.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-observation.d.ts +6 -0
- package/dist/assembly/webgpu-renderer-observation.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer-recovery-failure.d.ts +12 -0
- package/dist/assembly/webgpu-renderer-recovery-failure.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +7 -141
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/assembly/webgpu-vertex-layouts.d.ts +28 -84
- package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
- package/dist/authoring.mjs +3 -3
- package/dist/{chunk-ADHHVYLW.mjs → chunk-33XZFTQU.mjs} +245 -39
- package/dist/chunk-33XZFTQU.mjs.map +1 -0
- package/dist/{chunk-GF523LHF.mjs → chunk-BLXGONR2.mjs} +30 -12
- package/dist/chunk-BLXGONR2.mjs.map +1 -0
- package/dist/{chunk-KM2NOX2I.mjs → chunk-BQVQOQJH.mjs} +958 -254
- package/dist/chunk-BQVQOQJH.mjs.map +1 -0
- package/dist/{chunk-HKXTW355.mjs → chunk-BTWH7BP4.mjs} +386 -17
- package/dist/chunk-BTWH7BP4.mjs.map +1 -0
- package/dist/{chunk-TMIASV2N.mjs → chunk-FUODTTIA.mjs} +3934 -676
- package/dist/chunk-FUODTTIA.mjs.map +1 -0
- package/dist/{chunk-FJ6P52EE.mjs → chunk-ILQ5MEZF.mjs} +3 -17
- package/dist/chunk-ILQ5MEZF.mjs.map +1 -0
- package/dist/{chunk-E34VL5VI.mjs → chunk-JQTSEI3Z.mjs} +3 -3
- package/dist/{chunk-E34VL5VI.mjs.map → chunk-JQTSEI3Z.mjs.map} +1 -1
- package/dist/{chunk-GE3SDD72.mjs → chunk-NICXSHAT.mjs} +16 -38
- package/dist/chunk-NICXSHAT.mjs.map +1 -0
- package/dist/{chunk-ZZ4YQ474.mjs → chunk-NRNXBLIJ.mjs} +577 -7
- package/dist/chunk-NRNXBLIJ.mjs.map +1 -0
- package/dist/{chunk-JDWARUOI.mjs → chunk-PA5DRJNI.mjs} +17 -3
- package/dist/chunk-PA5DRJNI.mjs.map +1 -0
- package/dist/{chunk-XDP6XE5V.mjs → chunk-S4DNKQYQ.mjs} +1118 -446
- package/dist/chunk-S4DNKQYQ.mjs.map +1 -0
- package/dist/components/camera.d.ts +62 -2
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/instances.d.ts +6 -20
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/components/scene-instance.d.ts +2 -1
- package/dist/components/scene-instance.d.ts.map +1 -1
- package/dist/components/screen-space-reflection.d.ts +14 -0
- package/dist/components/screen-space-reflection.d.ts.map +1 -0
- package/dist/construct-renderer.mjs +13805 -7186
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +11 -17
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/device/mesh-residency-lifetime.d.ts +21 -0
- package/dist/device/mesh-residency-lifetime.d.ts.map +1 -0
- package/dist/dynamic-geometry.d.ts +125 -0
- package/dist/dynamic-geometry.d.ts.map +1 -0
- package/dist/environment/background.d.ts +6 -0
- package/dist/environment/background.d.ts.map +1 -0
- package/dist/errors/gpu-driven.d.ts +6 -3
- package/dist/errors/gpu-driven.d.ts.map +1 -1
- package/dist/errors/render.d.ts +7 -4
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +33 -3
- package/dist/extract/gpu-driven.d.ts.map +1 -1
- package/dist/features/host.d.ts +23 -1
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/noise-texture.d.ts +17 -0
- package/dist/features/noise-texture.d.ts.map +1 -0
- package/dist/features/plan.d.ts +83 -2
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +37 -4
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics-store.d.ts.map +1 -1
- package/dist/features/prepared-graphics.d.ts +5 -0
- package/dist/features/prepared-graphics.d.ts.map +1 -1
- package/dist/features/render-graph-compute.d.ts +5 -3
- package/dist/features/render-graph-compute.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts +11 -3
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/features/render-graph-raster.d.ts +19 -3
- package/dist/features/render-graph-raster.d.ts.map +1 -1
- package/dist/features/types.d.ts +11 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +2 -0
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts +34 -1
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/pbr-program.d.ts +10 -0
- package/dist/gpu-driven/pbr-program.d.ts.map +1 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +144 -23
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/shadow-views.d.ts +126 -0
- package/dist/gpu-driven/shadow-views.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +18 -2
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts +2 -8
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +14 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/gpu-texture-usage.d.ts +1 -0
- package/dist/gpu-texture-usage.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +6 -0
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/frame-resources.d.ts +8 -0
- package/dist/ibl/frame-resources.d.ts.map +1 -0
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +21 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +8 -7
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +164 -0
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances-derived-bounds.d.ts +11 -0
- package/dist/instances-derived-bounds.d.ts.map +1 -1
- package/dist/instances.d.ts +89 -44
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.d.ts +3 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +118 -10
- package/dist/internal.mjs.map +1 -1
- package/dist/lifecycle.d.ts +2 -1
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/material-row.d.ts +5 -0
- package/dist/material-row.d.ts.map +1 -0
- package/dist/materials.d.ts +15 -0
- package/dist/materials.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +21 -5
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-output/auto-exposure/capability.d.ts +12 -0
- package/dist/pipeline/standard-output/auto-exposure/capability.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts +70 -0
- package/dist/pipeline/standard-output/auto-exposure/gpu.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/graph.d.ts +75 -0
- package/dist/pipeline/standard-output/auto-exposure/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts +111 -0
- package/dist/pipeline/standard-output/auto-exposure/inspection.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts +16 -0
- package/dist/pipeline/standard-output/auto-exposure/oracle.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/preset.d.ts +14 -0
- package/dist/pipeline/standard-output/auto-exposure/preset.d.ts.map +1 -0
- package/dist/pipeline/standard-output/auto-exposure/state.d.ts +46 -0
- package/dist/pipeline/standard-output/auto-exposure/state.d.ts.map +1 -0
- package/dist/pipeline/standard-output/color-transform.d.ts +27 -0
- package/dist/pipeline/standard-output/color-transform.d.ts.map +1 -0
- package/dist/pipeline/standard-output/graph.d.ts +15 -0
- package/dist/pipeline/standard-output/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-output/lut-admission.d.ts +29 -0
- package/dist/pipeline/standard-output/lut-admission.d.ts.map +1 -0
- package/dist/pipeline/standard-output/lut-gpu.d.ts +48 -0
- package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -0
- package/dist/pipeline/standard-output/lut-state.d.ts +68 -0
- package/dist/pipeline/standard-output/lut-state.d.ts.map +1 -0
- package/dist/pipeline/standard-output/resources.d.ts +10 -0
- package/dist/pipeline/standard-output/resources.d.ts.map +1 -0
- package/dist/pipeline/standard-output/types.d.ts +39 -0
- package/dist/pipeline/standard-output/types.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +2 -2
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +2 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec-types.d.ts +4 -0
- package/dist/pipeline-spec-types.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +1 -9
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/points-lines/standard-owner.d.ts +1 -1
- package/dist/points-lines/standard-owner.d.ts.map +1 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts +6 -1
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
- package/dist/record/dynamic-geometry-consumption.d.ts +15 -0
- package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +3 -3
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +106 -5
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +39 -4
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +7 -8
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +38 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +2 -10
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +12 -2
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +15 -6
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/prepared-material-bindings.d.ts +19 -0
- package/dist/record/prepared-material-bindings.d.ts.map +1 -0
- package/dist/record/recovery-pipeline.d.ts +2 -9
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +76 -26
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +62 -7
- 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 +35 -7
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +1 -0
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +10 -2
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/recovery/render-system-roots.d.ts +11 -0
- package/dist/recovery/render-system-roots.d.ts.map +1 -0
- package/dist/recovery/types.d.ts +76 -0
- package/dist/recovery/types.d.ts.map +1 -0
- package/dist/reflection/record-owner.d.ts +0 -2
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +185 -30
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +1 -0
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +64 -5
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +7 -5
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +101 -41
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-projections.d.ts +22 -0
- package/dist/render-system-projections.d.ts.map +1 -0
- package/dist/render-system.d.ts +34 -77
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene-types.d.ts +14 -7
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +29 -11
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/shadow-visibility.d.ts +5 -0
- package/dist/scene/shadow-visibility.d.ts.map +1 -0
- package/dist/ssr/admission.d.ts +70 -1
- package/dist/ssr/admission.d.ts.map +1 -1
- package/dist/ssr/compose.d.ts +13 -0
- package/dist/ssr/compose.d.ts.map +1 -0
- package/dist/ssr/errors.d.ts +35 -0
- package/dist/ssr/errors.d.ts.map +1 -1
- package/dist/ssr/graph.d.ts +60 -0
- package/dist/ssr/graph.d.ts.map +1 -0
- package/dist/ssr/history.d.ts +97 -0
- package/dist/ssr/history.d.ts.map +1 -0
- package/dist/ssr/hiz.d.ts +37 -0
- package/dist/ssr/hiz.d.ts.map +1 -0
- package/dist/ssr/inspection.d.ts +42 -0
- package/dist/ssr/inspection.d.ts.map +1 -0
- package/dist/ssr/resources.d.ts +58 -0
- package/dist/ssr/resources.d.ts.map +1 -0
- package/dist/ssr/temporal.d.ts +38 -0
- package/dist/ssr/temporal.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +32 -10
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/systems/skin-palette-types.d.ts +15 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -1
- package/dist/systems/transparent-dispatch.d.ts +9 -0
- package/dist/systems/transparent-dispatch.d.ts.map +1 -0
- package/dist/targets/material-source.d.ts +7 -0
- package/dist/targets/material-source.d.ts.map +1 -1
- package/dist/temporal/frame-coordinator.d.ts +7 -0
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts +8 -0
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/history.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -6
- package/dist/temporal/inspection.d.ts.map +1 -1
- package/dist/temporal/standard-scene-data.d.ts +2 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/temporal-view.d.ts +2 -0
- package/dist/temporal/temporal-view.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +35 -1
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +3 -1
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/temporal.d.ts +6 -0
- package/dist/volume/temporal.d.ts.map +1 -1
- package/package.json +21 -20
- package/src/__tests__/auto-exposure-gpu-evidence.ts +291 -0
- package/src/__tests__/auto-exposure-inspection.unit.test.ts +80 -0
- package/src/__tests__/auto-exposure-transaction.integration.test.ts +99 -0
- package/src/__tests__/auto-exposure.browser.test.ts +33 -0
- package/src/__tests__/auto-exposure.dawn.test.ts +33 -0
- package/src/__tests__/detached-inspection.integration.test.ts +5 -0
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +18 -0
- package/src/__tests__/device-scope-stale-matrix.unit.test.ts +18 -0
- package/src/__tests__/docs-gate-green.unit.test.ts +3 -3
- package/src/__tests__/dynamic-geometry-host.unit.test.ts +1123 -0
- package/src/__tests__/dynamic-geometry.unit.test.ts +233 -0
- package/src/__tests__/factory-contract.integration.test.ts +73 -22
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +19 -0
- package/src/__tests__/feature-depth-input.dawn.test.ts +121 -0
- package/src/__tests__/feature-noise.unit.test.ts +38 -0
- package/src/__tests__/fixtures/taa-resolve-pinned-baseline.wgsl +301 -0
- package/src/__tests__/frame-camera-selection.unit.test.ts +131 -0
- package/src/__tests__/frame-plan-contract.unit.test.ts +24 -0
- package/src/__tests__/frame-targets.unit.test.ts +24 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +3 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +79 -0
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +287 -6
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +122 -142
- package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +10 -1
- package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +264 -0
- package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +349 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +1417 -0
- package/src/__tests__/gpu-driven-pbr.integration.test.ts +21 -0
- package/src/__tests__/gpu-driven-production-fixture.ts +96 -0
- package/src/__tests__/gpu-driven-production.integration.test.ts +1075 -93
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +1 -3
- package/src/__tests__/gpu-driven-shadow-views.browser.test.ts +63 -0
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +294 -0
- package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +97 -0
- package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +168 -0
- package/src/__tests__/gpu-driven-skin-contract.test-d.ts +11 -0
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +72 -20
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +30 -9
- package/src/__tests__/gpu-driven-view.unit.test.ts +159 -52
- package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -1
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +42 -0
- package/src/__tests__/gpu-scene-render-graph-gpu.ts +19 -5
- package/src/__tests__/gpu-scene.dawn.test.ts +40 -13
- package/src/__tests__/gpu-scene.unit.test.ts +559 -33
- package/src/__tests__/instances-culling.integration.test.ts +36 -10
- package/src/__tests__/instances-derived-bounds.unit.test.ts +54 -0
- package/src/__tests__/instances-store.unit.test.ts +242 -39
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +6 -0
- package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +13 -16
- package/src/__tests__/lut-lkg-transaction.integration.test.ts +122 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +5 -6
- package/src/__tests__/material-dispatch-shader-id.unit.test.ts +51 -0
- package/src/__tests__/material-lane-selection.unit.test.ts +60 -0
- package/src/__tests__/material-numeric-upload.unit.test.ts +53 -0
- package/src/__tests__/material-texture-handles.unit.test.ts +18 -0
- package/src/__tests__/material-texture-source.unit.test.ts +87 -0
- package/src/__tests__/materials-authoring-validation.unit.test.ts +41 -0
- package/src/__tests__/materials-standard-contract.unit.test.ts +52 -2
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +4 -0
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +53 -0
- package/src/__tests__/normal-fallback.dawn.test.ts +122 -0
- package/src/__tests__/particle-material-input-layout.unit.test.ts +104 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +37 -3
- package/src/__tests__/pipeline-texture-specialization.unit.test.ts +138 -0
- package/src/__tests__/point-shadow-inspection.unit.test.ts +2 -0
- package/src/__tests__/prepared-gpu-driven-pbr-contract.test-d.ts +31 -0
- package/src/__tests__/prepared-gpu-driven-pbr-contract.unit.test.ts +39 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +35 -4
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +21 -0
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +6 -2
- package/src/__tests__/profiler-phase-catalog.test.ts +5 -0
- package/src/__tests__/public-surface.test-d.ts +3 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +30 -12
- package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +104 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +2 -1
- package/src/__tests__/render-error-code-owner.test-d.ts +4 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +22 -0
- package/src/__tests__/render-error-exhaustive.test-d.ts +15 -0
- package/src/__tests__/render-feature-gpu-work.integration.test.ts +285 -2
- package/src/__tests__/render-feature-plan.unit.test.ts +245 -0
- package/src/__tests__/render-feature-shadow-order.unit.test.ts +228 -0
- package/src/__tests__/render-feature-zero-work.unit.test.ts +35 -1
- package/src/__tests__/render-graph-fallback.integration.test.ts +2 -2
- package/src/__tests__/render-owner-cohesion.unit.test.ts +55 -0
- package/src/__tests__/render-scene-mixed-updates.integration.test.ts +426 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +914 -23
- package/src/__tests__/render-scene-resource-updates.integration.test.ts +214 -0
- package/src/__tests__/render-scene-skin-lifecycle.integration.test.ts +173 -0
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +133 -0
- package/src/__tests__/render-target-material-source.test-d.ts +27 -3
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +61 -1
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +923 -5
- package/src/__tests__/shader-manifest-fixture.ts +39 -0
- package/src/__tests__/skin-motion-regression.unit.test.ts +0 -33
- package/src/__tests__/skin-palette-persistent.integration.test.ts +28 -0
- package/src/__tests__/skin-palette-persistent.unit.test.ts +247 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +118 -14
- package/src/__tests__/specular-environment-scale.dawn.test.ts +156 -0
- package/src/__tests__/ssr-admission-matrix.integration.test.ts +7 -1
- package/src/__tests__/ssr-confidence-compose.unit.test.ts +84 -0
- package/src/__tests__/ssr-coordinate-oracle.unit.test.ts +28 -0
- package/src/__tests__/ssr-format-probe-gating.integration.test.ts +82 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +91 -0
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +112 -0
- package/src/__tests__/ssr-gpu-dispatch.ts +946 -0
- package/src/__tests__/ssr-graph-topology.unit.test.ts +104 -0
- package/src/__tests__/ssr-history-filter.dawn.test.ts +198 -0
- package/src/__tests__/ssr-hit-color.dawn.test.ts +273 -0
- package/src/__tests__/ssr-hiz-odd-reduction.dawn.test.ts +569 -0
- package/src/__tests__/ssr-hiz-rescue.dawn.test.ts +279 -0
- package/src/__tests__/ssr-hiz.browser.test.ts +150 -0
- package/src/__tests__/ssr-hiz.dawn.test.ts +150 -0
- package/src/__tests__/ssr-hiz.unit.test.ts +56 -0
- package/src/__tests__/ssr-inspection.unit.test.ts +105 -0
- package/src/__tests__/ssr-memory-budget.unit.test.ts +45 -0
- package/src/__tests__/ssr-performance-sequence-aggregation.unit.test.ts +15 -0
- package/src/__tests__/ssr-public-surface.test-d.ts +37 -0
- package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +387 -0
- package/src/__tests__/ssr-reflection-mip-reducer.dawn.test.ts +309 -0
- package/src/__tests__/ssr-reprojection-probe.ts +90 -0
- package/src/__tests__/ssr-roughness-mip.dawn.test.ts +163 -0
- package/src/__tests__/ssr-shader-prewarm.unit.test.ts +59 -0
- package/src/__tests__/ssr-spatial.integration.test.ts +141 -0
- package/src/__tests__/ssr-stable-lattice.dawn.test.ts +475 -0
- package/src/__tests__/ssr-temporal-history.unit.test.ts +202 -0
- package/src/__tests__/ssr-texel-crossing.dawn.test.ts +448 -0
- package/src/__tests__/ssr-zero-work.integration.test.ts +87 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +44 -12
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +29 -0
- package/src/__tests__/standard-output-chain-contract.unit.test.ts +99 -0
- package/src/__tests__/standard-output-chain.integration.test.ts +73 -0
- package/src/__tests__/standard-output-gpu-evidence.ts +205 -0
- package/src/__tests__/standard-output.browser.test.ts +15 -0
- package/src/__tests__/standard-output.dawn.test.ts +15 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +38 -0
- package/src/__tests__/standard-pipeline.integration.test.ts +320 -3
- package/src/__tests__/standard-profile-oracle.unit.test.ts +22 -0
- package/src/__tests__/standard-surface-lighting.unit.test.ts +41 -0
- package/src/__tests__/standard-texture-specialization.dawn.test.ts +141 -0
- package/src/__tests__/surface-adjacent-regressions.integration.test.ts +6 -3
- package/src/__tests__/taa-coverage-edge.dawn.test.ts +193 -0
- package/src/__tests__/taa-history-clipping.dawn.test.ts +328 -0
- package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +778 -0
- package/src/__tests__/taa-stability-feedback.browser.test.ts +23 -0
- package/src/__tests__/taa-stability-feedback.dawn.test.ts +68 -0
- package/src/__tests__/taa-stability-feedback.ts +341 -0
- package/src/__tests__/temporal-history-lifecycle.unit.test.ts +49 -7
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +9 -0
- package/src/__tests__/temporal-transaction.integration.test.ts +28 -0
- package/src/__tests__/texture-usage-surface.unit.test.ts +4 -2
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +109 -4
- package/src/__tests__/typed-scene-pass-material-cache.integration.test.ts +126 -0
- package/src/__tests__/vertex-layouts-ssot.unit.test.ts +47 -0
- package/src/__tests__/visibility-extract.perf.test.ts +20 -8
- package/src/__tests__/visibility-instances.integration.test.ts +19 -7
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +20 -9
- package/src/assembly/atmosphere-shader-prewarm.ts +38 -0
- package/src/assembly/dynamic-geometry-host.ts +887 -0
- package/src/assembly/dynamic-geometry-runtime.ts +71 -0
- package/src/assembly/factory.ts +4 -0
- package/src/assembly/gpu-driven-owner.ts +29 -0
- package/src/assembly/host-contract.ts +36 -0
- package/src/assembly/material/assembly.ts +38 -0
- package/src/assembly/material-shader-policy.ts +71 -28
- package/src/assembly/recovery/failure-location.ts +62 -0
- package/src/assembly/recovery/renderer-recover.ts +19 -17
- package/src/assembly/renderer-facade.ts +29 -0
- package/src/assembly/renderer-feature-inspection.ts +13 -0
- package/src/assembly/renderer-frame-transaction.ts +63 -0
- package/src/assembly/renderer-helpers.ts +26 -0
- package/src/assembly/renderer-inspection.ts +6 -0
- package/src/assembly/shader-prewarm-policy.ts +32 -0
- package/src/assembly/skin-palette-owner.ts +21 -0
- package/src/assembly/ssr-shader-prewarm.ts +41 -0
- package/src/assembly/webgpu-device-loss.ts +75 -0
- package/src/assembly/webgpu-pbr-ready.ts +232 -0
- package/src/assembly/webgpu-ready-mipmap.ts +26 -0
- package/src/assembly/webgpu-ready.ts +142 -121
- package/src/assembly/webgpu-renderer-bootstrap.ts +85 -0
- package/src/assembly/webgpu-renderer-contract.ts +69 -0
- package/src/assembly/webgpu-renderer-guards.ts +32 -0
- package/src/assembly/webgpu-renderer-observation.ts +43 -0
- package/src/assembly/webgpu-renderer-recovery-failure.ts +62 -0
- package/src/assembly/webgpu-renderer.ts +675 -614
- package/src/assembly/webgpu-vertex-layouts.ts +233 -87
- package/src/components/__tests__/camera-exposure.contract.unit.test.ts +153 -0
- package/src/components/camera.ts +287 -7
- package/src/components/index.ts +1 -0
- package/src/components/instances.ts +45 -18
- package/src/components/scene-instance.ts +2 -1
- package/src/components/screen-space-reflection.ts +21 -0
- package/src/components/sprite-animation.ts +3 -3
- package/src/components/sprite-instances.ts +1 -1
- package/src/device/gpu-residency.ts +96 -93
- package/src/device/mesh-residency-lifetime.ts +73 -0
- package/src/dynamic-geometry.ts +736 -0
- package/src/environment/background.ts +263 -0
- package/src/errors/gpu-driven.ts +39 -5
- package/src/errors/render.ts +27 -3
- package/src/extract/camera.ts +26 -1
- package/src/extract/gpu-driven.ts +185 -10
- package/src/features/host.ts +237 -19
- package/src/features/noise-texture.ts +91 -0
- package/src/features/plan.ts +553 -24
- package/src/features/prepared-gpu-work.ts +631 -49
- package/src/features/prepared-graphics-store.ts +31 -0
- package/src/features/prepared-graphics.ts +5 -0
- package/src/features/render-graph-compute.ts +41 -8
- package/src/features/render-graph-contribution.ts +141 -3
- package/src/features/render-graph-raster.ts +143 -30
- package/src/features/types.ts +11 -0
- package/src/fullscreen-post-process-pass.ts +3 -0
- package/src/gpu-driven/batch-topology.ts +424 -102
- package/src/gpu-driven/pbr-program.ts +31 -0
- package/src/gpu-driven/prepared-draw.ts +29 -4
- package/src/gpu-driven/production-raster.ts +2267 -694
- package/src/gpu-driven/shadow-views.ts +539 -0
- package/src/gpu-driven/view-gpu.ts +188 -41
- package/src/gpu-scene-schema.ts +52 -11
- package/src/gpu-scene.ts +186 -99
- package/src/gpu-texture-usage.ts +1 -0
- package/src/hdrp-buffers.ts +72 -36
- package/src/ibl/frame-resources.ts +38 -0
- package/src/ibl/skylight-bind-group.ts +5 -4
- package/src/index.ts +125 -1
- package/src/inspection-types.ts +191 -0
- package/src/instances-derived-bounds.ts +258 -34
- package/src/instances.ts +459 -150
- package/src/internal.ts +22 -0
- package/src/lifecycle.ts +2 -0
- package/src/material-row.ts +145 -0
- package/src/materials.ts +44 -8
- package/src/pbr-pipeline.ts +159 -17
- package/src/pipeline/standard-forward-lane.ts +52 -24
- package/src/pipeline/standard-output/__tests__/lut-admission.unit.test.ts +103 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/capability.unit.test.ts +40 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/gpu.contract.unit.test.ts +125 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/graph.contract.unit.test.ts +94 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/oracle.test.ts +108 -0
- package/src/pipeline/standard-output/auto-exposure/__tests__/preset.test.ts +26 -0
- package/src/pipeline/standard-output/auto-exposure/capability.ts +38 -0
- package/src/pipeline/standard-output/auto-exposure/gpu.ts +567 -0
- package/src/pipeline/standard-output/auto-exposure/graph.ts +221 -0
- package/src/pipeline/standard-output/auto-exposure/inspection.ts +231 -0
- package/src/pipeline/standard-output/auto-exposure/oracle.ts +291 -0
- package/src/pipeline/standard-output/auto-exposure/preset.ts +28 -0
- package/src/pipeline/standard-output/auto-exposure/state.ts +156 -0
- package/src/pipeline/standard-output/color-transform.ts +124 -0
- package/src/pipeline/standard-output/graph.ts +139 -0
- package/src/pipeline/standard-output/lut-admission.ts +121 -0
- package/src/pipeline/standard-output/lut-gpu.ts +399 -0
- package/src/pipeline/standard-output/lut-state.ts +176 -0
- package/src/pipeline/standard-output/resources.ts +121 -0
- package/src/pipeline/standard-output/types.ts +58 -0
- package/src/pipeline/standard-pipeline.ts +192 -59
- package/src/pipeline/standard-post.ts +186 -27
- package/src/pipeline-builder.ts +16 -6
- package/src/pipeline-spec-types.ts +4 -0
- package/src/pipeline-spec.ts +37 -29
- package/src/points-lines/standard-owner.ts +6 -14
- package/src/prepare/prepared-graphics-resolver.ts +9 -2
- package/src/record/__tests__/material-slot-plan.unit.test.ts +48 -0
- package/src/record/__tests__/mesh-ssbo.unit.test.ts +40 -1
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +2 -29
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +36 -5
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +45 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +5 -0
- package/src/record/dynamic-geometry-consumption.ts +59 -0
- package/src/record/frame-lighting.ts +12 -11
- package/src/record/frame-snapshot.ts +133 -23
- package/src/record/frame-targets.ts +9 -0
- package/src/record/frame.ts +727 -133
- package/src/record/main-pass-geometry.ts +162 -98
- package/src/record/main-pass-material.ts +115 -26
- package/src/record/main-pass-sprite-draws.ts +18 -107
- package/src/record/main-pass.ts +78 -8
- package/src/record/material-uniforms.ts +1 -1
- package/src/record/mesh-ssbo.ts +59 -15
- package/src/record/prepared-material-bindings.ts +234 -0
- package/src/record/recovery-pipeline.ts +59 -136
- package/src/record/render-context.ts +92 -22
- package/src/record/shadow-pass.ts +1231 -209
- package/src/record/skybox-post-pass.ts +14 -3
- package/src/record/typed-frame-graph.ts +1006 -53
- package/src/record/view-ubo.ts +11 -0
- package/src/recovery/render-system-candidate.ts +90 -66
- package/src/recovery/render-system-roots.ts +113 -0
- package/src/recovery/types.ts +77 -0
- package/src/reflection/record-owner.ts +26 -54
- package/src/render-contract.ts +219 -25
- package/src/render-graph-primitives.ts +6 -2
- package/src/render-pipeline.ts +70 -1
- package/src/render-system-extract-tail.ts +409 -160
- package/src/render-system-extract.ts +376 -102
- package/src/render-system-projections.ts +241 -0
- package/src/render-system.ts +692 -791
- package/src/scene/render-scene-types.ts +13 -4
- package/src/scene/render-scene.ts +569 -355
- package/src/scene/shadow-visibility.ts +21 -0
- package/src/ssr/admission.ts +380 -14
- package/src/ssr/compose.ts +144 -0
- package/src/ssr/errors.ts +48 -0
- package/src/ssr/graph.ts +777 -0
- package/src/ssr/history.ts +436 -0
- package/src/ssr/hiz.ts +124 -0
- package/src/ssr/inspection.ts +124 -0
- package/src/ssr/resources.ts +202 -0
- package/src/ssr/temporal.ts +164 -0
- package/src/systems/skin-palette-allocator.ts +495 -148
- package/src/systems/skin-palette-types.ts +17 -0
- package/src/systems/transparent-dispatch.ts +90 -0
- package/src/targets/material-source.ts +34 -0
- package/src/temporal/coverage.ts +1 -1
- package/src/temporal/frame-coordinator.ts +23 -2
- package/src/temporal/gpu.ts +74 -12
- package/src/temporal/history.ts +3 -1
- package/src/temporal/inspection.ts +2 -1
- package/src/temporal/standard-scene-data.ts +3 -1
- package/src/temporal/temporal-view.ts +3 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +204 -139
- package/src/typed-render-graph-primitives.ts +266 -74
- package/src/typed-shadow-passes.ts +122 -12
- package/src/volume/temporal.ts +10 -0
- package/dist/chunk-ADHHVYLW.mjs.map +0 -1
- package/dist/chunk-FJ6P52EE.mjs.map +0 -1
- package/dist/chunk-GE3SDD72.mjs.map +0 -1
- package/dist/chunk-GF523LHF.mjs.map +0 -1
- package/dist/chunk-HKXTW355.mjs.map +0 -1
- package/dist/chunk-JDWARUOI.mjs.map +0 -1
- package/dist/chunk-KM2NOX2I.mjs.map +0 -1
- package/dist/chunk-TMIASV2N.mjs.map +0 -1
- package/dist/chunk-XDP6XE5V.mjs.map +0 -1
- package/dist/chunk-ZZ4YQ474.mjs.map +0 -1
- package/src/__tests__/instances-world-ownership.integration.test.ts +0 -62
- package/src/scene/__tests__/changed-block-summary.candidate.test.ts +0 -36
|
@@ -5,14 +5,12 @@ import {
|
|
|
5
5
|
} from '@forgeax/engine-assets-runtime';
|
|
6
6
|
import type { EntityHandle, World } from '@forgeax/engine-ecs';
|
|
7
7
|
import {
|
|
8
|
-
InstanceTransformsStrideMismatchError,
|
|
9
8
|
routeWorldError,
|
|
10
9
|
SpawnLightInvalidBoundsError,
|
|
11
10
|
SpriteInstancesCountMismatchError,
|
|
12
11
|
SpriteInstancesMutuallyExclusiveWithInstancesError,
|
|
13
12
|
SpriteInstancesRequiresSpriteShaderError,
|
|
14
13
|
} from '@forgeax/engine-ecs/projection';
|
|
15
|
-
import { deriveVertexLayoutProjection } from '@forgeax/engine-geometry';
|
|
16
14
|
import { box3, frustum, type Mat4, mat4, type Vec3, vec3 } from '@forgeax/engine-math';
|
|
17
15
|
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
18
16
|
import type { MaterialCookProgramContext } from '@forgeax/engine-pack/material-cook';
|
|
@@ -39,6 +37,7 @@ import {
|
|
|
39
37
|
ASSET_ERROR_HINTS,
|
|
40
38
|
AssetError,
|
|
41
39
|
derive,
|
|
40
|
+
err,
|
|
42
41
|
handleSlot,
|
|
43
42
|
materialValuesToLinearRuntime,
|
|
44
43
|
toShared,
|
|
@@ -81,16 +80,23 @@ import {
|
|
|
81
80
|
import { selectEnvironment } from './environment/frame';
|
|
82
81
|
import { MaterialSkinAttrMissingError, SkinMaterialMismatchError } from './errors/render';
|
|
83
82
|
import type { EnvironmentCandidate, EnvironmentFrame } from './extract/environment';
|
|
84
|
-
import {
|
|
83
|
+
import {
|
|
84
|
+
buildGpuDrivenDraws,
|
|
85
|
+
gpuDrivenShadowDrawKey,
|
|
86
|
+
gpuDrivenSourceDrawItemIndex,
|
|
87
|
+
} from './extract/gpu-driven';
|
|
85
88
|
import type { VisibilitySnapshot } from './extract/visibility';
|
|
86
89
|
import type {
|
|
87
90
|
RenderFeatureHiddenEntityReport,
|
|
88
91
|
RenderFeatureWorldVisibilitySnapshot,
|
|
89
92
|
} from './features/types';
|
|
90
93
|
import { ensureGlyphMeshMaterialSlots } from './glyph-text-layout-system';
|
|
91
|
-
import
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
import {
|
|
95
|
+
InstanceCollectionError,
|
|
96
|
+
type InstanceCollectionId,
|
|
97
|
+
type InstanceCollectionStore,
|
|
98
|
+
} from './instances';
|
|
99
|
+
import { deriveInstancesUnionBounds } from './instances-derived-bounds';
|
|
94
100
|
import {
|
|
95
101
|
type MeshMaterialBindingDiagnostic,
|
|
96
102
|
type MeshMaterialBindingSource,
|
|
@@ -101,6 +107,7 @@ import { expandPointsLinesBounds } from './points-lines/bounds';
|
|
|
101
107
|
import type { PointsLinesRetainedSnapshot, PointsLinesStyle } from './points-lines/snapshot';
|
|
102
108
|
import { COOKIE_SLICE_CAPACITY, IES_SLICE_CAPACITY } from './prepare/extended-lighting/resources';
|
|
103
109
|
import { prepareCookieProjection } from './prepare/extended-lighting/spot-modifiers';
|
|
110
|
+
import { worldEntityKey } from './record/frame-snapshot';
|
|
104
111
|
import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID } from './render-contract';
|
|
105
112
|
import type {
|
|
106
113
|
CsmCameraData,
|
|
@@ -116,12 +123,15 @@ import type {
|
|
|
116
123
|
MaterialSnapshot,
|
|
117
124
|
MaterialSnapshotCache,
|
|
118
125
|
MaterialSnapshotCachesByWorld,
|
|
126
|
+
MaterialTextureSourceCache,
|
|
127
|
+
MaterialTextureSourceStats,
|
|
119
128
|
MorphSnapshot,
|
|
120
129
|
PointLightSnapshot,
|
|
121
130
|
PointShadowSnapshot,
|
|
122
131
|
PreparedExtractContext,
|
|
123
132
|
RectAreaDirectLightSnapshot,
|
|
124
133
|
RenderableSnapshot,
|
|
134
|
+
ShadowCasterMembership,
|
|
125
135
|
SkyboxSnapshot,
|
|
126
136
|
SkylightSnapshot,
|
|
127
137
|
SpotLightSnapshot,
|
|
@@ -134,6 +144,8 @@ import {
|
|
|
134
144
|
BUILTIN_USER_REGION_TEXTURE_FIELDS,
|
|
135
145
|
buildPointShadowMatrices,
|
|
136
146
|
buildRectAreaWorldFrame,
|
|
147
|
+
collectAuthoredMaterialSamplerFields,
|
|
148
|
+
collectAuthoredMaterialTextureFields,
|
|
137
149
|
collectCubeCameraSnapshots,
|
|
138
150
|
collectMaterialTextureCoordinates,
|
|
139
151
|
collectMaterialTextureSamplers,
|
|
@@ -150,8 +162,10 @@ import {
|
|
|
150
162
|
materialNormalScale,
|
|
151
163
|
materialParamSchemaForMaterial,
|
|
152
164
|
materialProgramKeysForMaterial,
|
|
165
|
+
materialStandardTextureMask,
|
|
153
166
|
materialTextureFields,
|
|
154
167
|
materialTextureRef,
|
|
168
|
+
materialTextureSourceFields,
|
|
155
169
|
pipelineRenderState,
|
|
156
170
|
prepareExtractContext,
|
|
157
171
|
pssmSplit,
|
|
@@ -163,12 +177,19 @@ import {
|
|
|
163
177
|
Severity,
|
|
164
178
|
selectCameraRoles,
|
|
165
179
|
selectFogFrame,
|
|
180
|
+
shadowCasterCpuReason,
|
|
166
181
|
sortDispatchByQueue,
|
|
167
182
|
storeMaterialSnapshot,
|
|
168
183
|
tonemapParams,
|
|
169
184
|
} from './render-system-extract';
|
|
185
|
+
import { buildShadowFrusta } from './scene/shadow-visibility';
|
|
170
186
|
import { SHADOW_ATLAS_DEFAULT_LAYERS } from './shadow-atlas';
|
|
171
|
-
import type {
|
|
187
|
+
import type { SkinPaletteReceipt } from './systems/skin-palette-types';
|
|
188
|
+
|
|
189
|
+
function skinPaletteIdentity(world: World, entity: number): string {
|
|
190
|
+
return `skin:${world.identity}:${entity}`;
|
|
191
|
+
}
|
|
192
|
+
|
|
172
193
|
export function extractFrames(
|
|
173
194
|
worlds: readonly World[],
|
|
174
195
|
owner: number | ExtractFramesOwner,
|
|
@@ -178,13 +199,19 @@ export function extractFrames(
|
|
|
178
199
|
options: {
|
|
179
200
|
readonly materialContext?: MaterialCookProgramContext;
|
|
180
201
|
readonly cull?: 'normal' | 'none';
|
|
181
|
-
readonly renderables?:
|
|
182
|
-
|
|
202
|
+
readonly renderables?:
|
|
203
|
+
| 'full'
|
|
204
|
+
| 'none'
|
|
205
|
+
| {
|
|
206
|
+
readonly kind: 'partial';
|
|
207
|
+
readonly entitiesByWorld: readonly (ReadonlySet<number> | undefined)[];
|
|
208
|
+
};
|
|
183
209
|
readonly retainHidden?: boolean;
|
|
184
210
|
readonly getMaterialShaderArtifact?: (
|
|
185
211
|
materialShaderId: string,
|
|
212
|
+
vertexColorAvailable?: boolean,
|
|
186
213
|
) => MaterialShaderArtifact | undefined;
|
|
187
|
-
readonly instanceCollections?:
|
|
214
|
+
readonly instanceCollections?: InstanceCollectionStore;
|
|
188
215
|
} = {},
|
|
189
216
|
): ExtractedFrame {
|
|
190
217
|
// w4: normalize the owner argument. A bare number is the legacy single-owner
|
|
@@ -193,6 +220,12 @@ export function extractFrames(
|
|
|
193
220
|
// single-owner behaviour (w1 contract combination 2).
|
|
194
221
|
const cameraOwner = typeof owner === 'number' ? owner : owner.cameraOwner;
|
|
195
222
|
const resourceOwner = typeof owner === 'number' ? owner : owner.resourceOwner;
|
|
223
|
+
const cameraEntityKey = typeof owner === 'number' ? undefined : owner.cameraEntityKey;
|
|
224
|
+
const renderableRequest = options.renderables ?? 'full';
|
|
225
|
+
const renderableMode = typeof renderableRequest === 'object' ? 'full' : renderableRequest;
|
|
226
|
+
const partialEntitiesByWorld =
|
|
227
|
+
typeof renderableRequest === 'object' ? renderableRequest.entitiesByWorld : undefined;
|
|
228
|
+
const retainHidden = options.retainHidden ?? typeof renderableRequest === 'object';
|
|
196
229
|
|
|
197
230
|
// ── D-2: frame-level side effects live here ────────────────────────────
|
|
198
231
|
//
|
|
@@ -201,7 +234,14 @@ export function extractFrames(
|
|
|
201
234
|
// extract runs, so sequential per-world allocation yields non-overlapping
|
|
202
235
|
// palette slices (AC-08).
|
|
203
236
|
const skinPaletteAllocator = pipelineState?.skinPaletteAllocator ?? null;
|
|
204
|
-
|
|
237
|
+
// A partial request is still normalized to the producer's full renderable
|
|
238
|
+
// query, but it is not a full allocator reconciliation. beginFrame/endFrame
|
|
239
|
+
// mark every persistent identity not visited by this selected subset as
|
|
240
|
+
// detached; doing that here would release untouched palettes. Only the
|
|
241
|
+
// explicit full request is allowed to reconcile the identity set.
|
|
242
|
+
const reconcileSkinFrame = renderableRequest === 'full';
|
|
243
|
+
if (skinPaletteAllocator !== null && reconcileSkinFrame) {
|
|
244
|
+
skinPaletteAllocator.beginFrame();
|
|
205
245
|
skinPaletteAllocator.resetForFrame();
|
|
206
246
|
}
|
|
207
247
|
|
|
@@ -237,6 +277,13 @@ export function extractFrames(
|
|
|
237
277
|
const world = worlds[wi];
|
|
238
278
|
if (world === undefined || failedWorlds.has(world)) continue;
|
|
239
279
|
try {
|
|
280
|
+
if (skinPaletteAllocator !== null && partialEntitiesByWorld !== undefined) {
|
|
281
|
+
for (const entityKey of partialEntitiesByWorld[wi] ?? []) {
|
|
282
|
+
if (!world.hasComponent(entityKey as EntityHandle, Skin)) {
|
|
283
|
+
skinPaletteAllocator.releasePersistentSlice(skinPaletteIdentity(world, entityKey));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
240
287
|
const isCameraOwner = wi === cameraOwner;
|
|
241
288
|
const cameraOwnerFrame = framesByWorld.get(cameraOwner);
|
|
242
289
|
const prepared = prepareExtractContext(world, {
|
|
@@ -258,11 +305,13 @@ export function extractFrames(
|
|
|
258
305
|
? {}
|
|
259
306
|
: { materialContext: options.materialContext }),
|
|
260
307
|
cull: options.cull === 'none' ? 'none' : isCameraOwner ? 'self' : 'external',
|
|
261
|
-
renderables:
|
|
262
|
-
...(
|
|
308
|
+
renderables: renderableMode,
|
|
309
|
+
...(isCameraOwner && cameraEntityKey !== undefined ? { cameraEntityKey } : {}),
|
|
310
|
+
...(partialEntitiesByWorld?.[wi] === undefined
|
|
263
311
|
? {}
|
|
264
|
-
: { renderableEntities:
|
|
265
|
-
retainHidden
|
|
312
|
+
: { renderableEntities: partialEntitiesByWorld[wi] }),
|
|
313
|
+
retainHidden,
|
|
314
|
+
worldId: wi,
|
|
266
315
|
...(options.getMaterialShaderArtifact === undefined
|
|
267
316
|
? {}
|
|
268
317
|
: { getMaterialShaderArtifact: options.getMaterialShaderArtifact }),
|
|
@@ -287,6 +336,13 @@ export function extractFrames(
|
|
|
287
336
|
}
|
|
288
337
|
}
|
|
289
338
|
|
|
339
|
+
// Reconcile persistent palette identities from the extracted producer
|
|
340
|
+
// projection. Identities absent after a detach are fence-retired by the
|
|
341
|
+
// allocator; surviving identities keep their stable slices.
|
|
342
|
+
if (skinPaletteAllocator !== null && reconcileSkinFrame) {
|
|
343
|
+
skinPaletteAllocator.endFrame();
|
|
344
|
+
}
|
|
345
|
+
|
|
290
346
|
// Restore the caller's world order after the camera-owner-first extraction.
|
|
291
347
|
for (let wi = 0; wi < worlds.length; wi++) {
|
|
292
348
|
const frame = framesByWorld.get(wi);
|
|
@@ -300,6 +356,9 @@ export function extractFrames(
|
|
|
300
356
|
// AC-04: renderables — concat by worlds[] order, stamp worldId.
|
|
301
357
|
const renderables: RenderableSnapshot[] = [];
|
|
302
358
|
const dispatchEntries: DispatchEntry[] = [];
|
|
359
|
+
const shadowCasterEntityKeys = new Set<number>();
|
|
360
|
+
const shadowCasterDrawKeys = new Set<string>();
|
|
361
|
+
const shadowCasterMembership = new Map<string, ShadowCasterMembership>();
|
|
303
362
|
const visibilitySnapshots: VisibilitySnapshot[] = [];
|
|
304
363
|
const featureVisibilitySnapshots: RenderFeatureWorldVisibilitySnapshot[] = [];
|
|
305
364
|
const hiddenEntityReports: RenderFeatureHiddenEntityReport[] = [];
|
|
@@ -330,6 +389,18 @@ export function extractFrames(
|
|
|
330
389
|
for (const d of f.dispatch) {
|
|
331
390
|
dispatchEntries.push({ ...d, renderableIndex: (d.renderableIndex ?? 0) + base });
|
|
332
391
|
}
|
|
392
|
+
for (const key of f.shadowCasterEntityKeys) shadowCasterEntityKeys.add(key);
|
|
393
|
+
for (const key of f.shadowCasterDrawKeys) shadowCasterDrawKeys.add(key);
|
|
394
|
+
for (const membership of f.shadowCasterMembership ?? []) {
|
|
395
|
+
const rebased = { ...membership, renderableIndex: membership.renderableIndex + base };
|
|
396
|
+
const key = gpuDrivenShadowDrawKey(
|
|
397
|
+
rebased.worldEntity,
|
|
398
|
+
rebased.materialHandle,
|
|
399
|
+
rebased.drawItemIndex,
|
|
400
|
+
rebased.passIndex,
|
|
401
|
+
);
|
|
402
|
+
shadowCasterMembership.set(key, rebased);
|
|
403
|
+
}
|
|
333
404
|
}
|
|
334
405
|
|
|
335
406
|
// Stable sort dispatch by queue value.
|
|
@@ -359,11 +430,14 @@ export function extractFrames(
|
|
|
359
430
|
// camera may live in different worlds (editor super-composite).
|
|
360
431
|
let directionalCsmConfig: DirectionalCsmConfig | undefined;
|
|
361
432
|
let directionalCsmDirection: Vec3 | undefined;
|
|
362
|
-
for (
|
|
363
|
-
|
|
364
|
-
|
|
433
|
+
for (let fi = 0; fi < succeededFrames.length; fi += 1) {
|
|
434
|
+
const f = succeededFrames[fi];
|
|
435
|
+
const wId = succeededIndices[fi] ?? 0;
|
|
436
|
+
if (f === undefined) continue;
|
|
437
|
+
for (const p of f.lights.point) point.push({ ...p, worldId: wId });
|
|
438
|
+
for (const s of f.lights.spot) spot.push({ ...s, worldId: wId });
|
|
365
439
|
for (const r of f.lights.rect) rect.push(r);
|
|
366
|
-
for (const ps of f.lights.pointShadow) pointShadow.push(ps);
|
|
440
|
+
for (const ps of f.lights.pointShadow) pointShadow.push({ ...ps, worldId: wId });
|
|
367
441
|
if (directional === undefined && f.lights.directional !== undefined) {
|
|
368
442
|
directional = f.lights.directional;
|
|
369
443
|
// Carry CSM shadow fields from the first-hit directional's world.
|
|
@@ -393,9 +467,10 @@ export function extractFrames(
|
|
|
393
467
|
if (succeededIndices[fi] === cameraOwner) cameraOwnerFrame = succeededFrames[fi];
|
|
394
468
|
if (succeededIndices[fi] === resourceOwner) resourceOwnerFrame = succeededFrames[fi];
|
|
395
469
|
}
|
|
396
|
-
const cameras =
|
|
470
|
+
const cameras =
|
|
471
|
+
cameraOwnerFrame?.cameras.map((camera) => ({ ...camera, worldId: cameraOwner })) ?? [];
|
|
397
472
|
const auxiliaryCameras =
|
|
398
|
-
cameraOwnerFrame
|
|
473
|
+
cameraOwnerFrame?.auxiliaryCameras.map((camera) => ({ ...camera, worldId: cameraOwner })) ?? [];
|
|
399
474
|
const cubeCameras = cameraOwnerFrame !== undefined ? [...cameraOwnerFrame.cubeCameras] : [];
|
|
400
475
|
|
|
401
476
|
// bug-20260710-editor-cross-world-shadow: RECOMPUTE directional CSM matrices
|
|
@@ -460,6 +535,7 @@ export function extractFrames(
|
|
|
460
535
|
directionalCsmConfig,
|
|
461
536
|
directionalCsmDirection,
|
|
462
537
|
};
|
|
538
|
+
|
|
463
539
|
const volumetricFog = resourceOwnerFrame?.volumetricFog;
|
|
464
540
|
const skylight = resourceOwnerFrame?.skylight;
|
|
465
541
|
const skylightCount = resourceOwnerFrame?.skylightCount ?? 0;
|
|
@@ -468,7 +544,10 @@ export function extractFrames(
|
|
|
468
544
|
const fog = resourceOwnerFrame?.fog;
|
|
469
545
|
const fogFailure = resourceOwnerFrame?.fogFailure;
|
|
470
546
|
const environment = resourceOwnerFrame?.environment;
|
|
471
|
-
const lightProbes = succeededFrames.flatMap((frame) =>
|
|
547
|
+
const lightProbes = succeededFrames.flatMap((frame, index) => {
|
|
548
|
+
const worldId = succeededIndices[index] ?? 0;
|
|
549
|
+
return (frame.lightProbes ?? []).map((probe) => ({ ...probe, worldId }));
|
|
550
|
+
});
|
|
472
551
|
// User-authored PostProcessParams entities are singleton scene resources, so
|
|
473
552
|
// they come from the resourceOwner world (holistic snapshot selection).
|
|
474
553
|
const postProcessParams = new Map(resourceOwnerFrame?.postProcessParams);
|
|
@@ -507,35 +586,30 @@ export function extractFrames(
|
|
|
507
586
|
const visibilityStats = {
|
|
508
587
|
explicitlyHidden: succeededFrames.reduce((s, f) => s + f.visibilityStats.explicitlyHidden, 0),
|
|
509
588
|
};
|
|
589
|
+
const materialTextureSources: MaterialTextureSourceStats = {
|
|
590
|
+
sourceFieldsVisited: 0,
|
|
591
|
+
numericSharedRefProbes: 0,
|
|
592
|
+
sourceCacheHits: 0,
|
|
593
|
+
sourceCacheMisses: 0,
|
|
594
|
+
producerRoutes: {},
|
|
595
|
+
};
|
|
596
|
+
for (const frame of succeededFrames) {
|
|
597
|
+
const stats = frame.materialTextureSources;
|
|
598
|
+
if (stats === undefined) continue;
|
|
599
|
+
materialTextureSources.sourceFieldsVisited += stats.sourceFieldsVisited;
|
|
600
|
+
materialTextureSources.numericSharedRefProbes += stats.numericSharedRefProbes;
|
|
601
|
+
materialTextureSources.sourceCacheHits += stats.sourceCacheHits;
|
|
602
|
+
materialTextureSources.sourceCacheMisses += stats.sourceCacheMisses;
|
|
603
|
+
for (const [route, count] of Object.entries(stats.producerRoutes)) {
|
|
604
|
+
materialTextureSources.producerRoutes[route] =
|
|
605
|
+
(materialTextureSources.producerRoutes[route] ?? 0) + count;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
510
608
|
const reflectionProbes = succeededFrames.flatMap((f, index) => {
|
|
511
609
|
const worldId = succeededIndices[index] ?? 0;
|
|
512
610
|
return (f.reflectionProbes ?? []).map((probe) => ({ ...probe, worldId }));
|
|
513
611
|
});
|
|
514
612
|
|
|
515
|
-
if (options.renderables !== 'none' && options.renderableEntitiesByWorld === undefined) {
|
|
516
|
-
options.instanceCollections?.retain(
|
|
517
|
-
new Set(
|
|
518
|
-
renderables.flatMap((row) =>
|
|
519
|
-
row.instances?.collectionId === undefined ? [] : [row.instances.collectionId],
|
|
520
|
-
),
|
|
521
|
-
),
|
|
522
|
-
);
|
|
523
|
-
if (
|
|
524
|
-
skinPaletteAllocator !== null &&
|
|
525
|
-
typeof skinPaletteAllocator.retainSliceKeys === 'function'
|
|
526
|
-
) {
|
|
527
|
-
skinPaletteAllocator.retainSliceKeys(
|
|
528
|
-
new Set(
|
|
529
|
-
renderables.flatMap((row) =>
|
|
530
|
-
row.skin === undefined
|
|
531
|
-
? []
|
|
532
|
-
: [`${worlds[row.worldId]?.identity ?? row.worldId}:${row.entityKey}`],
|
|
533
|
-
),
|
|
534
|
-
),
|
|
535
|
-
);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
613
|
return {
|
|
540
614
|
cameras,
|
|
541
615
|
auxiliaryCameras,
|
|
@@ -547,6 +621,11 @@ export function extractFrames(
|
|
|
547
621
|
: { volumetricFog: { ...volumetricFog, worldId: resourceOwner } }),
|
|
548
622
|
renderables,
|
|
549
623
|
dispatch: dispatchEntries,
|
|
624
|
+
shadowCasterEntityKeys,
|
|
625
|
+
shadowCasterDrawKeys,
|
|
626
|
+
...(shadowCasterMembership.size === 0
|
|
627
|
+
? {}
|
|
628
|
+
: { shadowCasterMembership: [...shadowCasterMembership.values()] }),
|
|
550
629
|
skylight,
|
|
551
630
|
skylightCount,
|
|
552
631
|
lightProbes,
|
|
@@ -558,6 +637,7 @@ export function extractFrames(
|
|
|
558
637
|
environmentReady: resourceOwnerFrame !== undefined && environment !== undefined,
|
|
559
638
|
frustumStats,
|
|
560
639
|
visibilityStats,
|
|
640
|
+
materialTextureSources,
|
|
561
641
|
postProcessParams,
|
|
562
642
|
visibilitySnapshots,
|
|
563
643
|
featureVisibilitySnapshots,
|
|
@@ -656,6 +736,14 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
656
736
|
const fogFailure = fogState(world).failure;
|
|
657
737
|
const visibility = context.visibility.hasAnyHiddenIntent ? context.visibility : undefined;
|
|
658
738
|
const skinPaletteAllocator = pipelineState?.skinPaletteAllocator ?? null;
|
|
739
|
+
const materialTextureSourceStats: MaterialTextureSourceStats = {
|
|
740
|
+
sourceFieldsVisited: 0,
|
|
741
|
+
numericSharedRefProbes: 0,
|
|
742
|
+
sourceCacheHits: 0,
|
|
743
|
+
sourceCacheMisses: 0,
|
|
744
|
+
producerRoutes: {},
|
|
745
|
+
};
|
|
746
|
+
const materialTextureSourceCache: MaterialTextureSourceCache = new Map();
|
|
659
747
|
|
|
660
748
|
const directionalLightQuery = world.query({ read: [DirectionalLight] }).unwrap();
|
|
661
749
|
|
|
@@ -673,7 +761,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
673
761
|
const worldInternal = createWorldInternalView(world);
|
|
674
762
|
let volumetricFog = extractVolumeSnapshot(world, assets, worldInternal);
|
|
675
763
|
|
|
676
|
-
const cameraRoles = selectCameraRoles(world);
|
|
764
|
+
const cameraRoles = selectCameraRoles(world, context.cameraEntityKey);
|
|
677
765
|
const cameras = [...cameraRoles.display];
|
|
678
766
|
const auxiliaryCameras = cameraRoles.auxiliary;
|
|
679
767
|
const cubeCameras = collectCubeCameraSnapshots(world);
|
|
@@ -784,6 +872,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
784
872
|
pointSnapshots.push({
|
|
785
873
|
kind: 'point',
|
|
786
874
|
entity: entityId,
|
|
875
|
+
worldId: context.worldId,
|
|
787
876
|
position,
|
|
788
877
|
color: vec3.create(
|
|
789
878
|
(p.color[0] ?? 1) * intensity,
|
|
@@ -979,6 +1068,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
979
1068
|
spotSnapshots.push({
|
|
980
1069
|
kind: 'spot',
|
|
981
1070
|
entity: row.entity,
|
|
1071
|
+
worldId: context.worldId,
|
|
982
1072
|
// D-6: position reflects world transform; direction stays sourced
|
|
983
1073
|
// from SpotLight.direction (NOT rotated by the parent).
|
|
984
1074
|
position,
|
|
@@ -1274,10 +1364,13 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
1274
1364
|
}
|
|
1275
1365
|
pointShadowSnapshots.push({
|
|
1276
1366
|
entity: row.entity,
|
|
1367
|
+
worldId: context.worldId,
|
|
1277
1368
|
position: lightPos,
|
|
1278
1369
|
mapSize,
|
|
1279
1370
|
nearPlane,
|
|
1280
1371
|
farPlane,
|
|
1372
|
+
depthBias: ps.depthBias,
|
|
1373
|
+
normalBias: ps.normalBias,
|
|
1281
1374
|
shadowAtlasLayer: layer,
|
|
1282
1375
|
shadowMatrices: packed,
|
|
1283
1376
|
});
|
|
@@ -1329,6 +1422,12 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
1329
1422
|
directionalCsmDirection,
|
|
1330
1423
|
};
|
|
1331
1424
|
|
|
1425
|
+
// A caster may be outside the display camera while still contributing to a
|
|
1426
|
+
// light's shadow map. Keep the light-space visibility projection alongside
|
|
1427
|
+
// camera culling so the direct extraction path and persistent composition
|
|
1428
|
+
// retain the same shadow-only rule.
|
|
1429
|
+
const shadowFrusta = cullMode === 'none' ? [] : buildShadowFrusta(lights);
|
|
1430
|
+
|
|
1332
1431
|
// feat-20260520-skylight-ibl-cubemap M4 / t26+t27: query Skylight entities.
|
|
1333
1432
|
// First archetype hit wins (mirrors DirectionalLight pattern); multi-Skylight
|
|
1334
1433
|
// warn in record stage (t27) uses skylightCount.
|
|
@@ -1384,6 +1483,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
1384
1483
|
const transform = row.get(GlobalTransform);
|
|
1385
1484
|
lightProbes.push({
|
|
1386
1485
|
identity: String(row.entity),
|
|
1486
|
+
worldId: context.worldId,
|
|
1387
1487
|
position: [transform.world[12] ?? 0, transform.world[13] ?? 0, transform.world[14] ?? 0],
|
|
1388
1488
|
radius: probe.radius,
|
|
1389
1489
|
irradiance: new Float32Array(probe.irradiance),
|
|
@@ -1459,22 +1559,27 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
1459
1559
|
directionalDirection[1] ?? 0,
|
|
1460
1560
|
directionalDirection[2] ?? 0,
|
|
1461
1561
|
);
|
|
1562
|
+
const sunIntensity = directional?.intensity ?? 0;
|
|
1563
|
+
const sunColor =
|
|
1564
|
+
sunIntensity > 0 && directional !== undefined
|
|
1565
|
+
? ([
|
|
1566
|
+
(directional.color[0] ?? 0) / sunIntensity,
|
|
1567
|
+
(directional.color[1] ?? 0) / sunIntensity,
|
|
1568
|
+
(directional.color[2] ?? 0) / sunIntensity,
|
|
1569
|
+
] as [number, number, number])
|
|
1570
|
+
: ([0, 0, 0] as [number, number, number]);
|
|
1462
1571
|
const sun =
|
|
1463
|
-
directional === undefined || directionalLength <= 1e-6
|
|
1572
|
+
directional === undefined || directional.entity === undefined || directionalLength <= 1e-6
|
|
1464
1573
|
? []
|
|
1465
1574
|
: [
|
|
1466
1575
|
{
|
|
1467
|
-
entityKey:
|
|
1576
|
+
entityKey: directional.entity,
|
|
1468
1577
|
direction: [
|
|
1469
1578
|
-(directionalDirection?.[0] ?? 0) / directionalLength,
|
|
1470
1579
|
-(directionalDirection?.[1] ?? 0) / directionalLength,
|
|
1471
1580
|
-(directionalDirection?.[2] ?? 0) / directionalLength,
|
|
1472
1581
|
] as [number, number, number],
|
|
1473
|
-
color:
|
|
1474
|
-
directional.color[0] ?? 0,
|
|
1475
|
-
directional.color[1] ?? 0,
|
|
1476
|
-
directional.color[2] ?? 0,
|
|
1477
|
-
] as [number, number, number],
|
|
1582
|
+
color: sunColor,
|
|
1478
1583
|
intensity: directional.intensity,
|
|
1479
1584
|
},
|
|
1480
1585
|
];
|
|
@@ -1561,18 +1666,26 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
1561
1666
|
// (plan-strategy D-3). Entries built per-entity per-pass inside the
|
|
1562
1667
|
// archetype walk, then sorted by queue at the end.
|
|
1563
1668
|
let dispatch: DispatchEntry[] = [];
|
|
1669
|
+
const shadowMembershipEntries: ShadowCasterMembership[] = [];
|
|
1564
1670
|
// Keep the derived material snapshot and its resolved passes local to this
|
|
1565
1671
|
// extraction. Shared handles are immutable inputs for the frame, while
|
|
1566
1672
|
// dispatch entries still need to be rebuilt for each entity.
|
|
1567
1673
|
const materialSnapshotCache: MaterialSnapshotCache = new Map();
|
|
1674
|
+
// A collection can be associated with more than one entity. Snapshot its
|
|
1675
|
+
// renderer-owned bytes once per extracted frame so culling and every
|
|
1676
|
+
// submission lane consume the same detached revision without repeat copies.
|
|
1677
|
+
const instanceSnapshotCache = new Map<
|
|
1678
|
+
InstanceCollectionId,
|
|
1679
|
+
ReturnType<InstanceCollectionStore['snapshot']>
|
|
1680
|
+
>();
|
|
1568
1681
|
const skinnedMaterialSnapshotCache: MaterialSnapshotCache = new Map();
|
|
1569
1682
|
// tweak-20260611 M1: MeshRenderer renderable archetype walk routes
|
|
1570
1683
|
// through one World-owned Query. K-2 sniffing scheme B
|
|
1571
1684
|
// (`row.get(X) !== undefined` edge sniff) replaces the prior
|
|
1572
1685
|
// `arch.components.some` row-internal back-door. K-3 invariant: the
|
|
1573
1686
|
// variable-length array reads (`MeshRenderer.materials`, SpriteInstances
|
|
1574
|
-
// arrays) still flow through `_getArrayView`; explicit Instances bytes
|
|
1575
|
-
// from
|
|
1687
|
+
// arrays) still flow through `_getArrayView`; explicit Instances bytes come
|
|
1688
|
+
// from the renderer-owned collection store.
|
|
1576
1689
|
//
|
|
1577
1690
|
// archVersion remains the content fingerprint for SpriteInstances' managed
|
|
1578
1691
|
// arrays; explicit Instances use the collection revision below and never
|
|
@@ -1643,7 +1756,8 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
1643
1756
|
// are not materialised merely to answer a boolean question.
|
|
1644
1757
|
const hasTransform = row.has(Transform);
|
|
1645
1758
|
const meshFilter = row.get(MeshFilter);
|
|
1646
|
-
const
|
|
1759
|
+
const instancesData = row.get(Instances);
|
|
1760
|
+
const hasInstances = instancesData !== undefined;
|
|
1647
1761
|
const skin = row.get(Skin);
|
|
1648
1762
|
const morphWeightsView = worldInternal._getArrayView(row.entity, MorphWeights, 'weights');
|
|
1649
1763
|
const hasMeshFilter = meshFilter !== undefined;
|
|
@@ -1760,9 +1874,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
1760
1874
|
() => 'renderer-override',
|
|
1761
1875
|
);
|
|
1762
1876
|
let materialBindingDiagnostics: MeshMaterialBindingDiagnostic[] = [];
|
|
1763
|
-
let
|
|
1764
|
-
let gpuDrivenIndexed = false;
|
|
1765
|
-
let gpuDrivenGeometry: GpuDrivenGeometryReceipt | undefined;
|
|
1877
|
+
let gpuDrivenMesh: MeshAsset | undefined;
|
|
1766
1878
|
|
|
1767
1879
|
// Resolve instance overrides against mesh-owned slot defaults once.
|
|
1768
1880
|
const fAssetHandleVal = fAssetHandle;
|
|
@@ -1777,19 +1889,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
1777
1889
|
if (meshRes.ok && meshRes.value.kind === 'mesh') {
|
|
1778
1890
|
const meshAsset = meshRes.value as MeshAsset;
|
|
1779
1891
|
const guid = (meshRes.value as { guid?: string }).guid ?? '<no-guid>';
|
|
1780
|
-
|
|
1781
|
-
gpuDrivenIndexed = meshAsset.indices !== undefined;
|
|
1782
|
-
const layoutProjection = deriveVertexLayoutProjection(meshAsset.attributes);
|
|
1783
|
-
gpuDrivenGeometry = {
|
|
1784
|
-
identity: `${guid}:${layoutProjection.digest}`,
|
|
1785
|
-
vertexInputs: layoutProjection.attributes.map((attribute) => ({
|
|
1786
|
-
semantic: attribute.key,
|
|
1787
|
-
location: attribute.shaderLocation,
|
|
1788
|
-
format: attribute.format,
|
|
1789
|
-
})),
|
|
1790
|
-
topology: meshAsset.submeshes[0]?.topology ?? 'triangle-list',
|
|
1791
|
-
indexed: gpuDrivenIndexed,
|
|
1792
|
-
};
|
|
1892
|
+
gpuDrivenMesh = meshAsset;
|
|
1793
1893
|
// extractFrames is also a public read path and can run before the
|
|
1794
1894
|
// Renderer.draw pre-render stage. GlyphText proves the derived mesh
|
|
1795
1895
|
// owns exactly one Default slot; arbitrary meshes still fail closed
|
|
@@ -2241,6 +2341,16 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2241
2341
|
? assets.materialShaderTextureFieldNames(firstPassShader)
|
|
2242
2342
|
: undefined,
|
|
2243
2343
|
) ?? BUILTIN_USER_REGION_TEXTURE_FIELDS;
|
|
2344
|
+
const authoredTextureFields = collectAuthoredMaterialTextureFields(
|
|
2345
|
+
resolved.values,
|
|
2346
|
+
firstPassShader,
|
|
2347
|
+
materialParamSchema.length > 0 ? materialParamSchema : undefined,
|
|
2348
|
+
assets,
|
|
2349
|
+
);
|
|
2350
|
+
const authoredSamplerFields = collectAuthoredMaterialSamplerFields(
|
|
2351
|
+
resolved.values,
|
|
2352
|
+
authoredTextureFields,
|
|
2353
|
+
);
|
|
2244
2354
|
const textureHandles = new Map<string, Handle<'TextureAsset', 'shared'>>();
|
|
2245
2355
|
const videoTextureFields = new Map<string, Handle<'VideoAsset', 'shared'>>();
|
|
2246
2356
|
for (const field of userRegionFields) {
|
|
@@ -2274,7 +2384,15 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2274
2384
|
pv.occlusionTexture,
|
|
2275
2385
|
);
|
|
2276
2386
|
const textureCoordinates = collectMaterialTextureCoordinates(pv);
|
|
2277
|
-
const textureSources = collectMaterialTextureSources(
|
|
2387
|
+
const textureSources = collectMaterialTextureSources(
|
|
2388
|
+
pv,
|
|
2389
|
+
world,
|
|
2390
|
+
materialTextureSourceFields(
|
|
2391
|
+
materialParamSchema.length > 0 ? materialParamSchema : undefined,
|
|
2392
|
+
),
|
|
2393
|
+
materialTextureSourceStats,
|
|
2394
|
+
materialTextureSourceCache,
|
|
2395
|
+
);
|
|
2278
2396
|
const emissivePv = pv.emissive as readonly number[] | undefined;
|
|
2279
2397
|
// feat-20260625 M2 / w6: first-pass transparency flag folds into
|
|
2280
2398
|
// MaterialSnapshot.transparent so the record stage can drive the
|
|
@@ -2370,8 +2488,15 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2370
2488
|
renderState: pipelineRenderState(allPasses[0]?.renderState),
|
|
2371
2489
|
paramSnapshot: paramSnap,
|
|
2372
2490
|
...(materialParamSchema.length > 0 && { materialParamSchema }),
|
|
2491
|
+
standardTextureMask: materialStandardTextureMask(
|
|
2492
|
+
resolved.parameters,
|
|
2493
|
+
firstPassShader,
|
|
2494
|
+
pv,
|
|
2495
|
+
),
|
|
2373
2496
|
...(textureCoordinates.size > 0 && { textureCoordinates }),
|
|
2497
|
+
...(authoredTextureFields === undefined ? {} : { authoredTextureFields }),
|
|
2374
2498
|
...(samplerHandles.size > 0 && { samplerHandles }),
|
|
2499
|
+
...(authoredSamplerFields === undefined ? {} : { authoredSamplerFields }),
|
|
2375
2500
|
...(textureHandles.size > 0 && { textureHandles }),
|
|
2376
2501
|
...(textureSources.size > 0 && { textureSources }),
|
|
2377
2502
|
...(videoTextureFields.size > 0 && { videoTextureFields }),
|
|
@@ -2497,7 +2622,13 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2497
2622
|
// T-21 placeholder ({0,0} discriminator-only sentinel) with full
|
|
2498
2623
|
// resolve / validate / write chain (D-9 reset already fired at
|
|
2499
2624
|
// extractFrame entry; per-entity allocate + writeJointPalette here).
|
|
2500
|
-
let skinSlice:
|
|
2625
|
+
let skinSlice: SkinPaletteReceipt | undefined;
|
|
2626
|
+
const skinIdentity = hasSkin ? skinPaletteIdentity(world, entity) : undefined;
|
|
2627
|
+
const releaseSkinIdentity = (): void => {
|
|
2628
|
+
if (skinIdentity !== undefined) {
|
|
2629
|
+
skinPaletteAllocator?.releasePersistentSlice(skinIdentity);
|
|
2630
|
+
}
|
|
2631
|
+
};
|
|
2501
2632
|
if (hasSkin) {
|
|
2502
2633
|
const skeletonHandleRaw = skinSkeletonView;
|
|
2503
2634
|
if (
|
|
@@ -2512,7 +2643,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2512
2643
|
severity: Severity.Error,
|
|
2513
2644
|
systemName: 'RenderSystem.extract (skin-instances-coexist)',
|
|
2514
2645
|
});
|
|
2515
|
-
|
|
2646
|
+
releaseSkinIdentity();
|
|
2516
2647
|
continue;
|
|
2517
2648
|
}
|
|
2518
2649
|
// (a) Resolve skeleton asset; on failure -> skeleton-resolve-failed.
|
|
@@ -2523,13 +2654,17 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2523
2654
|
severity: Severity.Error,
|
|
2524
2655
|
systemName: 'RenderSystem.extract (skeleton-resolve-failed)',
|
|
2525
2656
|
});
|
|
2657
|
+
releaseSkinIdentity();
|
|
2526
2658
|
continue;
|
|
2527
2659
|
}
|
|
2528
2660
|
const skeleton = skeletonRes.value;
|
|
2529
2661
|
// (b) Reuse the Skin row already read for its skeleton handle;
|
|
2530
2662
|
// the old path repeated a second whole-row world.get here.
|
|
2531
2663
|
const skinJoints = skin?.joints;
|
|
2532
|
-
if (skinJoints === undefined)
|
|
2664
|
+
if (skinJoints === undefined) {
|
|
2665
|
+
releaseSkinIdentity();
|
|
2666
|
+
continue;
|
|
2667
|
+
}
|
|
2533
2668
|
const jointsLength = skinJoints.length;
|
|
2534
2669
|
if (jointsLength !== skeleton.jointCount) {
|
|
2535
2670
|
worldInternal._routeError(
|
|
@@ -2539,6 +2674,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2539
2674
|
systemName: 'RenderSystem.extract (joint-count-mismatch)',
|
|
2540
2675
|
},
|
|
2541
2676
|
);
|
|
2677
|
+
releaseSkinIdentity();
|
|
2542
2678
|
continue;
|
|
2543
2679
|
}
|
|
2544
2680
|
// (c) Resolve only each joint's GlobalTransform.world column. The
|
|
@@ -2569,6 +2705,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2569
2705
|
severity: Severity.Error,
|
|
2570
2706
|
systemName: 'RenderSystem.extract (joint-entity-dangling)',
|
|
2571
2707
|
});
|
|
2708
|
+
releaseSkinIdentity();
|
|
2572
2709
|
continue;
|
|
2573
2710
|
}
|
|
2574
2711
|
// (d) Slice the IBM flat Float32Array into per-joint Float32Arrays.
|
|
@@ -2578,29 +2715,25 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2578
2715
|
for (let jIdx = 0; jIdx < skeleton.jointCount; jIdx++) {
|
|
2579
2716
|
ibms[jIdx] = ibmFlat.subarray(jIdx * 16, jIdx * 16 + 16);
|
|
2580
2717
|
}
|
|
2581
|
-
// (e)
|
|
2582
|
-
//
|
|
2583
|
-
//
|
|
2584
|
-
//
|
|
2718
|
+
// (e) Reuse the persistent producer-owned slice for this stable
|
|
2719
|
+
// world/entity identity. Missing producer bounds remain explicit:
|
|
2720
|
+
// the receipt carries no invented bind-pose AABB and the shadow
|
|
2721
|
+
// admission lane can route the caster to CPU.
|
|
2585
2722
|
if (skinPaletteAllocator !== null) {
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
skinPaletteAllocator.
|
|
2599
|
-
skinSlice =
|
|
2600
|
-
jointCount: slice.jointCount,
|
|
2601
|
-
byteOffset: slice.byteOffset,
|
|
2602
|
-
buffer: slice.buffer,
|
|
2603
|
-
};
|
|
2723
|
+
const identity = skinPaletteIdentity(world, entity);
|
|
2724
|
+
const generation = (skeletonHandleRaw >>> 0) ^ skeleton.jointCount;
|
|
2725
|
+
const bounds = hasFiniteOrderedLocalAabb(skeleton.bounds)
|
|
2726
|
+
? new Float32Array(skeleton.bounds)
|
|
2727
|
+
: undefined;
|
|
2728
|
+
skinPaletteAllocator.observePersistentJoints(identity, ibms, jointWorlds);
|
|
2729
|
+
const receipt = skinPaletteAllocator.allocatePersistentSlice({
|
|
2730
|
+
identity,
|
|
2731
|
+
generation: generation >>> 0,
|
|
2732
|
+
jointCount: skeleton.jointCount,
|
|
2733
|
+
...(bounds === undefined ? {} : { bounds }),
|
|
2734
|
+
});
|
|
2735
|
+
skinPaletteAllocator.writePersistentJointPalette(receipt, ibms, jointWorlds);
|
|
2736
|
+
skinSlice = receipt;
|
|
2604
2737
|
}
|
|
2605
2738
|
}
|
|
2606
2739
|
}
|
|
@@ -2609,9 +2742,12 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2609
2742
|
// projection. Do not publish a renderable or its staged dispatch when
|
|
2610
2743
|
// palette extraction was unavailable; the record stage must never
|
|
2611
2744
|
// reinterpret a skinned vertex stream through an ordinary mesh group.
|
|
2612
|
-
if (
|
|
2613
|
-
|
|
2614
|
-
|
|
2745
|
+
if (skinSlice === undefined && hasSkin) {
|
|
2746
|
+
releaseSkinIdentity();
|
|
2747
|
+
if (materialSnap.materialShaderId === 'forgeax::pbr-skin') {
|
|
2748
|
+
pendingDispatch.length = 0;
|
|
2749
|
+
continue;
|
|
2750
|
+
}
|
|
2615
2751
|
}
|
|
2616
2752
|
|
|
2617
2753
|
// feat-20260601 D-3: read the resolved world mat4 (propagateTransforms
|
|
@@ -2622,7 +2758,10 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2622
2758
|
// tweak-20260611 M1 / K-3: `_getArrayView` call survives untouched;
|
|
2623
2759
|
// only the `entity` source switched to `bundle.Entity.self[i]`.
|
|
2624
2760
|
const worldView = worldInternal._getArrayView(entity, GlobalTransform, 'world');
|
|
2625
|
-
if (worldView === undefined)
|
|
2761
|
+
if (worldView === undefined) {
|
|
2762
|
+
releaseSkinIdentity();
|
|
2763
|
+
continue;
|
|
2764
|
+
}
|
|
2626
2765
|
const worldMat = new Float32Array(worldView);
|
|
2627
2766
|
const transformSnap: TransformSnapshot = { world: worldMat };
|
|
2628
2767
|
// feat-20260608 M5 amend / w11-a: per-submesh `materials[]` array
|
|
@@ -2654,6 +2793,8 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2654
2793
|
...context.materialContext,
|
|
2655
2794
|
geometry: hasSkin ? 'skinned' : context.materialContext.geometry,
|
|
2656
2795
|
},
|
|
2796
|
+
materialTextureSourceStats,
|
|
2797
|
+
materialTextureSourceCache,
|
|
2657
2798
|
),
|
|
2658
2799
|
);
|
|
2659
2800
|
}
|
|
@@ -2778,7 +2919,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2778
2919
|
lods = meshAsset.lods;
|
|
2779
2920
|
lodHysteresis = meshAsset.lodHysteresis;
|
|
2780
2921
|
morph = morphSnapshotFor(meshAsset, morphWeightsView);
|
|
2781
|
-
const meshAabb = meshAsset.aabb;
|
|
2922
|
+
const meshAabb = skinSlice?.bounds ?? meshAsset.aabb;
|
|
2782
2923
|
// Morph targets can expand the authored bounds. Keep the
|
|
2783
2924
|
// specialized lane conservative until a target-aware bounds
|
|
2784
2925
|
// projection is available; a false-positive draw is preferable
|
|
@@ -2805,7 +2946,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2805
2946
|
pointsLinesComponent === undefined
|
|
2806
2947
|
? undefined
|
|
2807
2948
|
: ({
|
|
2808
|
-
worldId:
|
|
2949
|
+
worldId: context.worldId,
|
|
2809
2950
|
entityKey: entity,
|
|
2810
2951
|
component: pointsLinesComponent,
|
|
2811
2952
|
meshHandle: assetHandleRaw,
|
|
@@ -2828,30 +2969,48 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2828
2969
|
// make the cull and draw disagree within one frame).
|
|
2829
2970
|
let instancesSnap: InstancesSnapshot | undefined;
|
|
2830
2971
|
if (hasInstances) {
|
|
2831
|
-
const
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2972
|
+
const collectionId = instancesData?.collectionId as InstanceCollectionId | undefined;
|
|
2973
|
+
let collectionResult =
|
|
2974
|
+
collectionId !== undefined ? instanceSnapshotCache.get(collectionId) : undefined;
|
|
2975
|
+
if (collectionResult === undefined) {
|
|
2976
|
+
collectionResult =
|
|
2977
|
+
collectionId !== undefined && collectionId > 0 && instanceCollections !== undefined
|
|
2978
|
+
? instanceCollections.snapshot(collectionId)
|
|
2979
|
+
: err(
|
|
2980
|
+
new InstanceCollectionError(
|
|
2981
|
+
'instance-collection-invalid',
|
|
2982
|
+
'Instances.collectionId references a live renderer-owned collection',
|
|
2983
|
+
'create the collection through renderer.instances before attaching Instances',
|
|
2984
|
+
{
|
|
2985
|
+
operation: 'inspect',
|
|
2986
|
+
expected: 'a positive collectionId with a live renderer owner',
|
|
2987
|
+
actual: Number(collectionId ?? 0),
|
|
2988
|
+
...(collectionId === undefined ? {} : { collectionId }),
|
|
2989
|
+
},
|
|
2990
|
+
),
|
|
2991
|
+
);
|
|
2992
|
+
if (collectionId !== undefined)
|
|
2993
|
+
instanceSnapshotCache.set(collectionId, collectionResult);
|
|
2994
|
+
}
|
|
2995
|
+
if (collectionResult === undefined) continue;
|
|
2996
|
+
if (!collectionResult.ok) {
|
|
2997
|
+
worldInternal._routeError(collectionResult.error, {
|
|
2998
|
+
severity: Severity.Error,
|
|
2999
|
+
systemName: 'RenderSystem.extract (Instances collection)',
|
|
3000
|
+
});
|
|
2841
3001
|
continue;
|
|
2842
3002
|
}
|
|
2843
|
-
const projected = instanceCollections?.project(world, entity, transforms);
|
|
2844
3003
|
instancesSnap = {
|
|
2845
|
-
transforms:
|
|
2846
|
-
instanceCount:
|
|
3004
|
+
transforms: collectionResult.value.transforms,
|
|
3005
|
+
instanceCount: collectionResult.value.count,
|
|
3006
|
+
collectionId: collectionResult.value.collectionId,
|
|
3007
|
+
revision: collectionResult.value.revision,
|
|
3008
|
+
capacity: collectionResult.value.capacity,
|
|
3009
|
+
dirtyRanges: collectionResult.value.dirtyRanges,
|
|
2847
3010
|
cacheKey: entity,
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
: {
|
|
2852
|
-
collectionId: projected.collectionId,
|
|
2853
|
-
revision: projected.revision,
|
|
2854
|
-
}),
|
|
3011
|
+
// Explicit collection revisions supersede ECS archetype content
|
|
3012
|
+
// hashes; retain zero as the legacy sprite-only field value.
|
|
3013
|
+
archVersion: 0,
|
|
2855
3014
|
};
|
|
2856
3015
|
}
|
|
2857
3016
|
|
|
@@ -2865,7 +3024,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2865
3024
|
materials: materialsArr,
|
|
2866
3025
|
materialBindingSources,
|
|
2867
3026
|
materialBindingDiagnostics,
|
|
2868
|
-
worldId:
|
|
3027
|
+
worldId: context.worldId,
|
|
2869
3028
|
entityKey: entity,
|
|
2870
3029
|
...(authorVisible ? {} : { authorVisible: false }),
|
|
2871
3030
|
...(skinSlice !== undefined ? { skin: skinSlice } : {}),
|
|
@@ -2878,34 +3037,27 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2878
3037
|
...(pointsLines !== undefined ? { pointsLines } : {}),
|
|
2879
3038
|
};
|
|
2880
3039
|
const gpuDrivenDraws = buildGpuDrivenDraws({
|
|
2881
|
-
|
|
2882
|
-
indexed: gpuDrivenIndexed,
|
|
3040
|
+
mesh: gpuDrivenMesh,
|
|
2883
3041
|
materials: materialsArr,
|
|
2884
3042
|
fallbackMaterial: materialSnap,
|
|
2885
|
-
|
|
3043
|
+
baseSnapshot: baseRenderable,
|
|
3044
|
+
...(getMaterialShaderArtifact === undefined ? {} : { getMaterialShaderArtifact }),
|
|
3045
|
+
...(lods === undefined
|
|
2886
3046
|
? {}
|
|
2887
3047
|
: {
|
|
2888
|
-
|
|
2889
|
-
const
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
if (artifact?.receipt === undefined) return undefined;
|
|
2893
|
-
const geometry: GpuDrivenGeometryReceipt = {
|
|
2894
|
-
...gpuDrivenGeometry,
|
|
2895
|
-
topology: draw.topology,
|
|
2896
|
-
indexed: draw.kind === 'indexed',
|
|
2897
|
-
};
|
|
2898
|
-
const result = resolvePreparedGpuDrivenDraw({
|
|
2899
|
-
snapshot: { ...baseRenderable, material: drawMaterial },
|
|
2900
|
-
artifact,
|
|
2901
|
-
geometry,
|
|
2902
|
-
generation: artifact.receipt.generation,
|
|
2903
|
-
draw,
|
|
2904
|
-
});
|
|
2905
|
-
return result.ok ? result.value : undefined;
|
|
2906
|
-
},
|
|
3048
|
+
lodMeshes: lods.map((lod) => {
|
|
3049
|
+
const lower = assets?.lookup<Asset>(lod.mesh);
|
|
3050
|
+
return lower?.kind === 'mesh' ? lower : undefined;
|
|
3051
|
+
}),
|
|
2907
3052
|
}),
|
|
2908
3053
|
});
|
|
3054
|
+
for (const draw of gpuDrivenDraws) {
|
|
3055
|
+
if (draw.preparationError === undefined) continue;
|
|
3056
|
+
worldInternal._routeError(draw.preparationError, {
|
|
3057
|
+
severity: Severity.Error,
|
|
3058
|
+
systemName: `RenderSystem.extract (gpu-driven-preparation:${draw.preparationError.code})`,
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
2909
3061
|
const renderable =
|
|
2910
3062
|
morph === undefined && gpuDrivenDraws.length > 0
|
|
2911
3063
|
? { ...baseRenderable, gpuDrivenDraws }
|
|
@@ -2975,13 +3127,81 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2975
3127
|
}
|
|
2976
3128
|
if (!visible) {
|
|
2977
3129
|
frustumCulled += 1;
|
|
2978
|
-
|
|
3130
|
+
const shadowVisible =
|
|
3131
|
+
shadowFrusta.length > 0 &&
|
|
3132
|
+
pendingDispatch.some((entry) => entry.tags.LightMode === 'ShadowCaster') &&
|
|
3133
|
+
shadowFrusta.some((lightPlanes) =>
|
|
3134
|
+
frustum.intersectsBox(lightPlanes, worldAabb as box3.Box3Like),
|
|
3135
|
+
);
|
|
3136
|
+
if (!shadowVisible) continue;
|
|
3137
|
+
// Shadow-only renderables stay in the detached snapshot for the
|
|
3138
|
+
// depth passes, but must not leak their forward/transparent
|
|
3139
|
+
// dispatch entries into the main camera submission.
|
|
3140
|
+
for (let i = pendingDispatch.length - 1; i >= 0; i -= 1) {
|
|
3141
|
+
if (pendingDispatch[i]?.tags.LightMode !== 'ShadowCaster') {
|
|
3142
|
+
pendingDispatch.splice(i, 1);
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
2979
3145
|
}
|
|
2980
3146
|
}
|
|
2981
3147
|
}
|
|
2982
3148
|
|
|
3149
|
+
const localShadowMembershipEntries: ShadowCasterMembership[] = [];
|
|
3150
|
+
if (gpuDrivenMesh !== undefined) {
|
|
3151
|
+
const worldEntity = worldEntityKey(context.worldId, entity);
|
|
3152
|
+
for (const [drawItemIndex, submesh] of gpuDrivenMesh.submeshes.entries()) {
|
|
3153
|
+
if (submesh.topology !== 'triangle-list' && submesh.topology !== 'triangle-strip') {
|
|
3154
|
+
continue;
|
|
3155
|
+
}
|
|
3156
|
+
const material = materialsArr[submesh.materialSlot] ?? materialSnap;
|
|
3157
|
+
const materialHandle = material.materialHandle ?? -1;
|
|
3158
|
+
const shadowEntries = pendingDispatch.filter(
|
|
3159
|
+
(entry) =>
|
|
3160
|
+
entry.tags.LightMode === 'ShadowCaster' && entry.materialHandle === materialHandle,
|
|
3161
|
+
);
|
|
3162
|
+
const draw = renderable.gpuDrivenDraws?.find(
|
|
3163
|
+
(candidate, compactIndex) =>
|
|
3164
|
+
gpuDrivenSourceDrawItemIndex(candidate, compactIndex) === drawItemIndex,
|
|
3165
|
+
);
|
|
3166
|
+
const cpuReason = shadowCasterCpuReason(
|
|
3167
|
+
material,
|
|
3168
|
+
draw,
|
|
3169
|
+
shadowEntries,
|
|
3170
|
+
morph,
|
|
3171
|
+
skinSlice,
|
|
3172
|
+
);
|
|
3173
|
+
for (const entry of shadowEntries) {
|
|
3174
|
+
const membership: ShadowCasterMembership = {
|
|
3175
|
+
worldEntity,
|
|
3176
|
+
renderableIndex: renderables.length,
|
|
3177
|
+
drawItemIndex,
|
|
3178
|
+
materialHandle,
|
|
3179
|
+
passIndex: entry.passIndex,
|
|
3180
|
+
...(entry.materialShaderId === undefined
|
|
3181
|
+
? {}
|
|
3182
|
+
: { materialShaderId: entry.materialShaderId }),
|
|
3183
|
+
...(entry.renderState === undefined ? {} : { renderState: entry.renderState }),
|
|
3184
|
+
...(cpuReason === undefined ? {} : { cpuReason }),
|
|
3185
|
+
};
|
|
3186
|
+
shadowMembershipEntries.push(membership);
|
|
3187
|
+
localShadowMembershipEntries.push(membership);
|
|
3188
|
+
}
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
const shadowCasterPasses = localShadowMembershipEntries.map((membership) => ({
|
|
3192
|
+
drawItemIndex: membership.drawItemIndex,
|
|
3193
|
+
materialHandle: membership.materialHandle,
|
|
3194
|
+
passIndex: membership.passIndex,
|
|
3195
|
+
...(membership.materialShaderId === undefined
|
|
3196
|
+
? {}
|
|
3197
|
+
: { materialShaderId: membership.materialShaderId }),
|
|
3198
|
+
...(membership.renderState === undefined ? {} : { renderState: membership.renderState }),
|
|
3199
|
+
...(membership.cpuReason === undefined ? {} : { cpuReason: membership.cpuReason }),
|
|
3200
|
+
}));
|
|
3201
|
+
const renderableWithShadowPasses =
|
|
3202
|
+
shadowCasterPasses.length === 0 ? renderable : { ...renderable, shadowCasterPasses };
|
|
2983
3203
|
flushPendingDispatch(pendingDispatch);
|
|
2984
|
-
renderables.push(
|
|
3204
|
+
renderables.push(renderableWithShadowPasses);
|
|
2985
3205
|
}
|
|
2986
3206
|
|
|
2987
3207
|
// feat-20260520-2d-sprite-layer-mvp M-3 / w22 + w25: finalise the
|
|
@@ -2998,6 +3218,28 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
2998
3218
|
// M3 / w26: sort dispatch entries by queue (ascending, stable sort)
|
|
2999
3219
|
// per plan-strategy D-3.
|
|
3000
3220
|
dispatch = sortDispatchByQueue(dispatch);
|
|
3221
|
+
const shadowCasterEntityKeys = new Set<number>();
|
|
3222
|
+
const shadowCasterDrawKeys = new Set<string>();
|
|
3223
|
+
const shadowCasterMembership = new Map<string, ShadowCasterMembership>();
|
|
3224
|
+
for (const entry of dispatch) {
|
|
3225
|
+
if (entry.tags.LightMode !== 'ShadowCaster') continue;
|
|
3226
|
+
const renderable = renderables[entry.renderableIndex];
|
|
3227
|
+
if (renderable !== undefined) {
|
|
3228
|
+
const worldEntity = worldEntityKey(renderable.worldId, renderable.entityKey);
|
|
3229
|
+
shadowCasterEntityKeys.add(worldEntity);
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
for (const membership of shadowMembershipEntries) {
|
|
3233
|
+
const key = gpuDrivenShadowDrawKey(
|
|
3234
|
+
membership.worldEntity,
|
|
3235
|
+
membership.materialHandle,
|
|
3236
|
+
membership.drawItemIndex,
|
|
3237
|
+
membership.passIndex,
|
|
3238
|
+
);
|
|
3239
|
+
shadowCasterDrawKeys.add(key);
|
|
3240
|
+
shadowCasterMembership.set(key, membership);
|
|
3241
|
+
shadowCasterEntityKeys.add(membership.worldEntity);
|
|
3242
|
+
}
|
|
3001
3243
|
|
|
3002
3244
|
// D-1: collect PostProcessParams entities into Map<shaderId, Uint8Array>.
|
|
3003
3245
|
// Last-one-wins when multiple entities bear the same shader id (mirrors
|
|
@@ -3041,6 +3283,11 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
3041
3283
|
...(volumetricFog === undefined ? {} : { volumetricFog }),
|
|
3042
3284
|
renderables,
|
|
3043
3285
|
dispatch,
|
|
3286
|
+
shadowCasterEntityKeys,
|
|
3287
|
+
shadowCasterDrawKeys,
|
|
3288
|
+
...(shadowCasterMembership.size === 0
|
|
3289
|
+
? {}
|
|
3290
|
+
: { shadowCasterMembership: [...shadowCasterMembership.values()] }),
|
|
3044
3291
|
skylight,
|
|
3045
3292
|
skylightCount,
|
|
3046
3293
|
lightProbes,
|
|
@@ -3050,6 +3297,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
3050
3297
|
...(fogFailure === undefined ? {} : { fogFailure }),
|
|
3051
3298
|
frustumStats: { culled: frustumCulled, total: frustumTotal },
|
|
3052
3299
|
visibilityStats: { explicitlyHidden: explicitlyHidden.size },
|
|
3300
|
+
materialTextureSources: materialTextureSourceStats,
|
|
3053
3301
|
postProcessParams,
|
|
3054
3302
|
visibilitySnapshots: [context.visibility],
|
|
3055
3303
|
featureVisibilitySnapshots: [{ world, snapshot: context.visibility }],
|
|
@@ -3057,17 +3305,18 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
|
|
|
3057
3305
|
};
|
|
3058
3306
|
}
|
|
3059
3307
|
|
|
3308
|
+
/** Immutable author-independent default; extraction retains its producer identity. */
|
|
3309
|
+
const DEFAULT_MATERIAL_SNAPSHOT: MaterialSnapshot = Object.freeze({
|
|
3310
|
+
baseColor: vec3.create(0.5, 0.5, 0.5),
|
|
3311
|
+
metallic: 0,
|
|
3312
|
+
roughness: 1,
|
|
3313
|
+
materialHandle: 0,
|
|
3314
|
+
});
|
|
3315
|
+
|
|
3060
3316
|
export function defaultMaterialSnapshot(materialHandle = 0): MaterialSnapshot {
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
// unlit fallback shader was selected.
|
|
3065
|
-
return {
|
|
3066
|
-
baseColor: vec3.create(0.5, 0.5, 0.5),
|
|
3067
|
-
metallic: 0,
|
|
3068
|
-
roughness: 1,
|
|
3069
|
-
materialHandle,
|
|
3070
|
-
};
|
|
3317
|
+
return materialHandle === 0
|
|
3318
|
+
? DEFAULT_MATERIAL_SNAPSHOT
|
|
3319
|
+
: { ...DEFAULT_MATERIAL_SNAPSHOT, materialHandle };
|
|
3071
3320
|
}
|
|
3072
3321
|
|
|
3073
3322
|
function identityProjection(): Float32Array {
|