@forgeax/engine-render 0.0.0-dev.8d955ade1c79
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/LICENSE +202 -0
- package/README.md +647 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/__tests__/authoring-path.unit.test.d.ts +2 -0
- package/dist/__tests__/authoring-path.unit.test.d.ts.map +1 -0
- package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts +2 -0
- package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts.map +1 -0
- package/dist/__tests__/callback-inference.test-d.d.ts +2 -0
- package/dist/__tests__/callback-inference.test-d.d.ts.map +1 -0
- package/dist/__tests__/cluster-binner.test.d.ts +2 -0
- package/dist/__tests__/cluster-binner.test.d.ts.map +1 -0
- package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/construct-renderer-identity.unit.test.d.ts +2 -0
- package/dist/__tests__/construct-renderer-identity.unit.test.d.ts.map +1 -0
- 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__/direct-extract-consumer-contract.test-d.d.ts +2 -0
- package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts.map +1 -0
- package/dist/__tests__/direct-light-snapshot.unit.test.d.ts +2 -0
- package/dist/__tests__/direct-light-snapshot.unit.test.d.ts.map +1 -0
- package/dist/__tests__/factory-contract.integration.test.d.ts +2 -0
- package/dist/__tests__/factory-contract.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/frame-observation.contract.test.d.ts +2 -0
- package/dist/__tests__/frame-observation.contract.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__/glyph-text-layout-recovery.unit.test.d.ts +2 -0
- package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts +6 -0
- package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-production.integration.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-production.integration.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +18 -0
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view-reference.d.ts +15 -0
- package/dist/__tests__/gpu-driven-view-reference.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view.browser.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-view.browser.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view.dawn.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-view.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-view.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts +7 -0
- package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-schema.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene-schema.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene.dawn.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene.unit.test.d.ts.map +1 -0
- 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__/infinite-grid-no-vertex-probe.unit.test.d.ts +2 -0
- package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts.map +1 -0
- package/dist/__tests__/injection-kind-owner.test-d.d.ts +2 -0
- package/dist/__tests__/injection-kind-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts +2 -0
- package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/light-buffer-layout.unit.test.d.ts +2 -0
- package/dist/__tests__/light-buffer-layout.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-contract-inventory.unit.test.d.ts +2 -0
- package/dist/__tests__/material-contract-inventory.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-cooked-projection.unit.test.d.ts +2 -0
- package/dist/__tests__/material-cooked-projection.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts +2 -0
- package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts.map +1 -0
- package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts +2 -0
- package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-stride-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/material-stride-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-material-bindings.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-material-bindings.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-stride-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-stride-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts +2 -0
- package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts +2 -0
- package/dist/__tests__/morph-feature-gpu-work.integration.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__/morph-visual-evidence.integration.test.d.ts +2 -0
- package/dist/__tests__/morph-visual-evidence.integration.test.d.ts.map +1 -0
- package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts +2 -0
- package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts +2 -0
- package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-store.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-store.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts.map +1 -0
- package/dist/__tests__/profiler-default-off.test.d.ts +2 -0
- package/dist/__tests__/profiler-default-off.test.d.ts.map +1 -0
- package/dist/__tests__/profiler-phase-catalog.test.d.ts +2 -0
- package/dist/__tests__/profiler-phase-catalog.test.d.ts.map +1 -0
- package/dist/__tests__/profiler-phase-integration.test.d.ts +2 -0
- package/dist/__tests__/profiler-phase-integration.test.d.ts.map +1 -0
- package/dist/__tests__/profiler-phase-token.test.d.ts +2 -0
- package/dist/__tests__/profiler-phase-token.test.d.ts.map +1 -0
- package/dist/__tests__/public-surface.test-d.d.ts +2 -0
- package/dist/__tests__/public-surface.test-d.d.ts.map +1 -0
- package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts +2 -0
- package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-error-code-owner.test-d.d.ts +2 -0
- package/dist/__tests__/render-error-code-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-error-detail-ssot.test-d.d.ts +2 -0
- package/dist/__tests__/render-error-detail-ssot.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts +2 -0
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-assembly.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-assembly.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-context.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-context.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-contract.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-contract.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-docs.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-docs.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-errors.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-errors.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts +2 -0
- package/dist/__tests__/render-feature-gpu-work.integration.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__/render-feature-prepared-diagnostics.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-public-surface.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-public-surface.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-retry.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-retry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-scheduling.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-scheduling.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-visibility-context.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-visibility-context.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-zero-work.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-zero-work.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-compute-raster-gpu.d.ts +7 -0
- package/dist/__tests__/render-graph-compute-raster-gpu.d.ts.map +1 -0
- package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts +2 -0
- package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts +2 -0
- package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-hzb-gpu.d.ts +7 -0
- package/dist/__tests__/render-graph-hzb-gpu.d.ts.map +1 -0
- package/dist/__tests__/render-graph-hzb.browser.test.d.ts +2 -0
- package/dist/__tests__/render-graph-hzb.browser.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-hzb.dawn.test.d.ts +2 -0
- package/dist/__tests__/render-graph-hzb.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-primitives.unit.test.d.ts +2 -0
- package/dist/__tests__/render-graph-primitives.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts +12 -0
- package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts.map +1 -0
- package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts +2 -0
- package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts +2 -0
- package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/render-scene-projection.unit.test.d.ts +2 -0
- package/dist/__tests__/render-scene-projection.unit.test.d.ts.map +1 -0
- package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/renderer-lifecycle.integration.test.d.ts +2 -0
- package/dist/__tests__/renderer-lifecycle.integration.test.d.ts.map +1 -0
- package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts +2 -0
- package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts.map +1 -0
- package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts +2 -0
- package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts.map +1 -0
- package/dist/__tests__/shader-stage-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/shader-stage-surface.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__/ssao-kernel-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/ssao-kernel-surface.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__/surface-configuration.unit.test.d.ts +2 -0
- package/dist/__tests__/surface-configuration.unit.test.d.ts.map +1 -0
- package/dist/__tests__/texture-usage-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/texture-usage-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts +2 -0
- package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts.map +1 -0
- package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts +2 -0
- package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts.map +1 -0
- package/dist/__tests__/urp-pipeline.unit.test.d.ts +2 -0
- package/dist/__tests__/urp-pipeline.unit.test.d.ts.map +1 -0
- package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts +2 -0
- package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts.map +1 -0
- package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts +2 -0
- package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-diagnostics.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-diagnostics.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-extract.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-extract.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-extract.perf.test.d.ts +2 -0
- package/dist/__tests__/visibility-extract.perf.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-hidden-report.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-hidden-report.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-instances.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-instances.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-multi-world.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-multi-world.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-public-surface.test-d.d.ts +2 -0
- package/dist/__tests__/visibility-public-surface.test-d.d.ts.map +1 -0
- package/dist/__tests__/visibility-resolver.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-resolver.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/__tests__/visibility-snapshot-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/vocabulary.unit.test.d.ts +2 -0
- package/dist/__tests__/vocabulary.unit.test.d.ts.map +1 -0
- package/dist/assembly/backend-contract.d.ts +37 -0
- 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/assembly/material/assembly.d.ts +21 -0
- package/dist/assembly/material/assembly.d.ts.map +1 -0
- package/dist/assembly/material/pipeline-projection.d.ts +30 -0
- package/dist/assembly/material/pipeline-projection.d.ts.map +1 -0
- package/dist/assets/asset-decoders.d.ts +5 -0
- package/dist/assets/asset-decoders.d.ts.map +1 -0
- package/dist/assets/render-asset-port.d.ts +17 -0
- package/dist/assets/render-asset-port.d.ts.map +1 -0
- package/dist/assets/resolve-render-asset.d.ts +6 -0
- package/dist/assets/resolve-render-asset.d.ts.map +1 -0
- package/dist/authoring.d.ts +12 -0
- package/dist/authoring.d.ts.map +1 -0
- package/dist/authoring.mjs +27 -0
- package/dist/authoring.mjs.map +1 -0
- package/dist/chunk-CQXZC5XI.mjs +182 -0
- package/dist/chunk-CQXZC5XI.mjs.map +1 -0
- package/dist/chunk-HCOGPHKS.mjs +93 -0
- package/dist/chunk-HCOGPHKS.mjs.map +1 -0
- package/dist/chunk-YEJIUW7D.mjs +1152 -0
- package/dist/chunk-YEJIUW7D.mjs.map +1 -0
- package/dist/cluster-binner.d.ts +152 -0
- package/dist/cluster-binner.d.ts.map +1 -0
- package/dist/components/__tests__/points-lines-admission.unit.test.d.ts +2 -0
- package/dist/components/__tests__/points-lines-admission.unit.test.d.ts.map +1 -0
- package/dist/components/__tests__/points-lines-schema.unit.test.d.ts +2 -0
- package/dist/components/__tests__/points-lines-schema.unit.test.d.ts.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/__tests__/schema-parity.unit.test.d.ts +2 -0
- package/dist/components/__tests__/schema-parity.unit.test.d.ts.map +1 -0
- package/dist/components/__tests__/visibility-schema.unit.test.d.ts +2 -0
- package/dist/components/__tests__/visibility-schema.unit.test.d.ts.map +1 -0
- package/dist/components/camera.d.ts +311 -0
- package/dist/components/camera.d.ts.map +1 -0
- package/dist/components/directional-light.d.ts +76 -0
- package/dist/components/directional-light.d.ts.map +1 -0
- package/dist/components/glyph-text.d.ts +26 -0
- package/dist/components/glyph-text.d.ts.map +1 -0
- package/dist/components/index.d.ts +24 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/instances.d.ts +41 -0
- package/dist/components/instances.d.ts.map +1 -0
- package/dist/components/layer.d.ts +34 -0
- package/dist/components/layer.d.ts.map +1 -0
- package/dist/components/light-helpers.d.ts +53 -0
- package/dist/components/light-helpers.d.ts.map +1 -0
- package/dist/components/lines.d.ts +5 -0
- package/dist/components/lines.d.ts.map +1 -0
- package/dist/components/mesh-filter.d.ts +24 -0
- package/dist/components/mesh-filter.d.ts.map +1 -0
- package/dist/components/mesh-renderer.d.ts +33 -0
- package/dist/components/mesh-renderer.d.ts.map +1 -0
- package/dist/components/point-light-shadow.d.ts +27 -0
- package/dist/components/point-light-shadow.d.ts.map +1 -0
- package/dist/components/point-light.d.ts +35 -0
- package/dist/components/point-light.d.ts.map +1 -0
- package/dist/components/points.d.ts +15 -0
- package/dist/components/points.d.ts.map +1 -0
- package/dist/components/post-process-params.d.ts +5 -0
- package/dist/components/post-process-params.d.ts.map +1 -0
- package/dist/components/scene-instance.d.ts +140 -0
- package/dist/components/scene-instance.d.ts.map +1 -0
- 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/sort-key.d.ts +44 -0
- package/dist/components/sort-key.d.ts.map +1 -0
- package/dist/components/spot-light.d.ts +81 -0
- package/dist/components/spot-light.d.ts.map +1 -0
- package/dist/components/sprite-animation.d.ts +74 -0
- package/dist/components/sprite-animation.d.ts.map +1 -0
- package/dist/components/sprite-instances.d.ts +51 -0
- package/dist/components/sprite-instances.d.ts.map +1 -0
- package/dist/components/sprite-playback-mode.d.ts +42 -0
- package/dist/components/sprite-playback-mode.d.ts.map +1 -0
- package/dist/components/sprite-region-override.d.ts +46 -0
- package/dist/components/sprite-region-override.d.ts.map +1 -0
- package/dist/components/tile-layer.d.ts +106 -0
- package/dist/components/tile-layer.d.ts.map +1 -0
- package/dist/components/tilemap.d.ts +25 -0
- package/dist/components/tilemap.d.ts.map +1 -0
- package/dist/components/visibility.d.ts +22 -0
- package/dist/components/visibility.d.ts.map +1 -0
- package/dist/construct-renderer.d.ts +19 -0
- package/dist/construct-renderer.d.ts.map +1 -0
- package/dist/construct-renderer.mjs +27462 -0
- package/dist/construct-renderer.mjs.map +1 -0
- package/dist/debug-draw-glue.d.ts +5 -0
- package/dist/debug-draw-glue.d.ts.map +1 -0
- package/dist/device/device-scope.d.ts +83 -0
- package/dist/device/device-scope.d.ts.map +1 -0
- package/dist/device/gpu-residency.d.ts +337 -0
- 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 +23 -0
- package/dist/engine-metrics.d.ts.map +1 -0
- package/dist/errors/ecs-validation.d.ts +3 -0
- package/dist/errors/ecs-validation.d.ts.map +1 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/recover.d.ts +105 -0
- package/dist/errors/recover.d.ts.map +1 -0
- package/dist/errors/render.d.ts +705 -0
- package/dist/errors/render.d.ts.map +1 -0
- package/dist/extract/visibility.d.ts +26 -0
- package/dist/extract/visibility.d.ts.map +1 -0
- package/dist/features/fullscreen.d.ts +19 -0
- package/dist/features/fullscreen.d.ts.map +1 -0
- package/dist/features/host.d.ts +106 -0
- package/dist/features/host.d.ts.map +1 -0
- package/dist/features/morph/morph-feature.d.ts +79 -0
- package/dist/features/morph/morph-feature.d.ts.map +1 -0
- 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 +117 -0
- package/dist/features/prepared-gpu-work.d.ts.map +1 -0
- package/dist/features/prepared-graphics-store.d.ts +66 -0
- package/dist/features/prepared-graphics-store.d.ts.map +1 -0
- package/dist/features/prepared-graphics.d.ts +215 -0
- package/dist/features/prepared-graphics.d.ts.map +1 -0
- package/dist/features/render-graph-compute.d.ts +13 -0
- package/dist/features/render-graph-compute.d.ts.map +1 -0
- package/dist/features/render-graph-contribution.d.ts +12 -0
- package/dist/features/render-graph-contribution.d.ts.map +1 -0
- package/dist/features/render-graph-raster.d.ts +38 -0
- package/dist/features/render-graph-raster.d.ts.map +1 -0
- package/dist/features/render-graph-resources.d.ts +11 -0
- package/dist/features/render-graph-resources.d.ts.map +1 -0
- package/dist/features/targets.d.ts +32 -0
- package/dist/features/targets.d.ts.map +1 -0
- package/dist/features/types.d.ts +68 -0
- package/dist/features/types.d.ts.map +1 -0
- 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 +157 -0
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -0
- package/dist/glyph-text-layout-system.d.ts +19 -0
- package/dist/glyph-text-layout-system.d.ts.map +1 -0
- package/dist/gpu-driven/batch-topology.d.ts +55 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +51 -0
- package/dist/gpu-driven/production-raster.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +85 -0
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -0
- package/dist/gpu-resource.d.ts +73 -0
- package/dist/gpu-resource.d.ts.map +1 -0
- package/dist/gpu-scene-schema.d.ts +78 -0
- package/dist/gpu-scene-schema.d.ts.map +1 -0
- package/dist/gpu-scene.d.ts +55 -0
- package/dist/gpu-scene.d.ts.map +1 -0
- package/dist/gpu-stage.d.ts +4 -0
- package/dist/gpu-stage.d.ts.map +1 -0
- package/dist/gpu-texture-usage.d.ts +6 -0
- package/dist/gpu-texture-usage.d.ts.map +1 -0
- package/dist/gpu-usage.d.ts +9 -0
- package/dist/gpu-usage.d.ts.map +1 -0
- package/dist/hdrp-buffers.d.ts +163 -0
- package/dist/hdrp-buffers.d.ts.map +1 -0
- package/dist/ibl/IblPipelineCache.d.ts +168 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -0
- package/dist/ibl/skylight-bind-group.d.ts +130 -0
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +169 -0
- package/dist/index.mjs.map +1 -0
- package/dist/inspection-types.d.ts +72 -0
- package/dist/inspection-types.d.ts.map +1 -0
- package/dist/instance-buffer-cache.d.ts +56 -0
- package/dist/instance-buffer-cache.d.ts.map +1 -0
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.mjs +3 -0
- package/dist/internal.mjs.map +1 -0
- package/dist/lifecycle.d.ts +62 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/light-buffer-layout.d.ts +164 -0
- package/dist/light-buffer-layout.d.ts.map +1 -0
- package/dist/materials.d.ts +47 -0
- package/dist/materials.d.ts.map +1 -0
- package/dist/mesh-material-bindings.d.ts +43 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -0
- package/dist/pbr-pipeline.d.ts +301 -0
- package/dist/pbr-pipeline.d.ts.map +1 -0
- 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 +122 -0
- package/dist/pipeline-builder.d.ts.map +1 -0
- 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 +367 -0
- package/dist/pipeline-spec.d.ts.map +1 -0
- package/dist/plugin.d.ts +4 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/points-lines/__tests__/bounds.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/bounds.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts +2 -0
- package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/inspection.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/inspection.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts +2 -0
- package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/points-lines.bench.d.ts +2 -0
- package/dist/points-lines/__tests__/points-lines.bench.d.ts.map +1 -0
- package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts +2 -0
- package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/snapshot.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/snapshot.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts.map +1 -0
- package/dist/points-lines/admission.d.ts +36 -0
- package/dist/points-lines/admission.d.ts.map +1 -0
- package/dist/points-lines/bounds.d.ts +8 -0
- package/dist/points-lines/bounds.d.ts.map +1 -0
- package/dist/points-lines/expansion-cache.d.ts +28 -0
- package/dist/points-lines/expansion-cache.d.ts.map +1 -0
- package/dist/points-lines/inspection.d.ts +53 -0
- package/dist/points-lines/inspection.d.ts.map +1 -0
- package/dist/points-lines/prepare.d.ts +67 -0
- package/dist/points-lines/prepare.d.ts.map +1 -0
- package/dist/points-lines/record.d.ts +60 -0
- package/dist/points-lines/record.d.ts.map +1 -0
- package/dist/points-lines/snapshot.d.ts +49 -0
- package/dist/points-lines/snapshot.d.ts.map +1 -0
- package/dist/post-process-errors.d.ts +182 -0
- package/dist/post-process-errors.d.ts.map +1 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts +59 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -0
- package/dist/record/__tests__/material-bg-cache.unit.test.d.ts +2 -0
- package/dist/record/__tests__/material-bg-cache.unit.test.d.ts.map +1 -0
- package/dist/record/__tests__/material-slot-plan.unit.test.d.ts +2 -0
- package/dist/record/__tests__/material-slot-plan.unit.test.d.ts.map +1 -0
- 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/__tests__/video-texture-view.unit.test.d.ts +2 -0
- package/dist/record/__tests__/video-texture-view.unit.test.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +121 -0
- package/dist/record/frame-lighting.d.ts.map +1 -0
- package/dist/record/frame-snapshot.d.ts +429 -0
- package/dist/record/frame-snapshot.d.ts.map +1 -0
- package/dist/record/frame-targets.d.ts +20 -0
- package/dist/record/frame-targets.d.ts.map +1 -0
- package/dist/record/frame.d.ts +71 -0
- package/dist/record/frame.d.ts.map +1 -0
- package/dist/record/helpers.d.ts +102 -0
- package/dist/record/helpers.d.ts.map +1 -0
- package/dist/record/main-pass-geometry.d.ts +28 -0
- package/dist/record/main-pass-geometry.d.ts.map +1 -0
- package/dist/record/main-pass-material.d.ts +204 -0
- package/dist/record/main-pass-material.d.ts.map +1 -0
- package/dist/record/main-pass-sprite-draws.d.ts +43 -0
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -0
- package/dist/record/main-pass.d.ts +20 -0
- package/dist/record/main-pass.d.ts.map +1 -0
- package/dist/record/mesh-ssbo.d.ts +446 -0
- package/dist/record/mesh-ssbo.d.ts.map +1 -0
- package/dist/record/render-context.d.ts +252 -0
- package/dist/record/render-context.d.ts.map +1 -0
- package/dist/record/shadow-pass.d.ts +52 -0
- package/dist/record/shadow-pass.d.ts.map +1 -0
- package/dist/record/skybox-post-pass.d.ts +33 -0
- package/dist/record/skybox-post-pass.d.ts.map +1 -0
- package/dist/record/typed-frame-graph.d.ts +35 -0
- package/dist/record/typed-frame-graph.d.ts.map +1 -0
- package/dist/record/view-ubo.d.ts +45 -0
- package/dist/record/view-ubo.d.ts.map +1 -0
- package/dist/render-contract.d.ts +424 -0
- package/dist/render-contract.d.ts.map +1 -0
- package/dist/render-data.d.ts +143 -0
- package/dist/render-data.d.ts.map +1 -0
- package/dist/render-graph-primitives.d.ts +76 -0
- package/dist/render-graph-primitives.d.ts.map +1 -0
- package/dist/render-pipeline.d.ts +110 -0
- package/dist/render-pipeline.d.ts.map +1 -0
- package/dist/render-system-extract.d.ts +868 -0
- package/dist/render-system-extract.d.ts.map +1 -0
- package/dist/render-system.d.ts +125 -0
- package/dist/render-system.d.ts.map +1 -0
- package/dist/scene/render-scene-types.d.ts +61 -0
- package/dist/scene/render-scene-types.d.ts.map +1 -0
- package/dist/scene/render-scene.d.ts +112 -0
- package/dist/scene/render-scene.d.ts.map +1 -0
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts +30 -0
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -0
- package/dist/shadow-atlas.d.ts +117 -0
- package/dist/shadow-atlas.d.ts.map +1 -0
- package/dist/ssao-buffers.d.ts +50 -0
- package/dist/ssao-buffers.d.ts.map +1 -0
- package/dist/ssao-config.d.ts +28 -0
- package/dist/ssao-config.d.ts.map +1 -0
- package/dist/systems/active-camera.d.ts +53 -0
- package/dist/systems/active-camera.d.ts.map +1 -0
- package/dist/systems/pass-selector.d.ts +24 -0
- package/dist/systems/pass-selector.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +49 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -0
- 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 +112 -0
- package/dist/systems/transparent-sort-config.d.ts.map +1 -0
- package/dist/tilemap-chunk-extract-system.d.ts +143 -0
- package/dist/tilemap-chunk-extract-system.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +57 -0
- package/dist/typed-render-graph-primitives.d.ts.map +1 -0
- package/dist/typed-shadow-passes.d.ts +11 -0
- package/dist/typed-shadow-passes.d.ts.map +1 -0
- package/package.json +94 -0
- package/src/__tests__/authoring-path.unit.test.ts +23 -0
- package/src/__tests__/backend-selection-rhi-capture.test-d.ts +21 -0
- package/src/__tests__/callback-inference.test-d.ts +8 -0
- package/src/__tests__/cluster-binner.test.ts +272 -0
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +20 -0
- package/src/__tests__/construct-renderer-identity.unit.test.ts +23 -0
- 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 +23 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +61 -0
- package/src/__tests__/factory-contract.integration.test.ts +280 -0
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +15 -0
- package/src/__tests__/frame-observation.contract.test.ts +112 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
- package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +167 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +350 -0
- package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +12 -0
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +16 -0
- package/src/__tests__/gpu-driven-production.integration.test.ts +436 -0
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +87 -0
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +271 -0
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +290 -0
- package/src/__tests__/gpu-driven-view-reference.ts +111 -0
- package/src/__tests__/gpu-driven-view.browser.test.ts +30 -0
- package/src/__tests__/gpu-driven-view.dawn.test.ts +28 -0
- package/src/__tests__/gpu-driven-view.unit.test.ts +199 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +59 -0
- package/src/__tests__/gpu-scene-render-graph-gpu.ts +308 -0
- package/src/__tests__/gpu-scene-render-graph.browser.test.ts +19 -0
- package/src/__tests__/gpu-scene-render-graph.dawn.test.ts +19 -0
- package/src/__tests__/gpu-scene-schema.unit.test.ts +16 -0
- package/src/__tests__/gpu-scene.dawn.test.ts +205 -0
- package/src/__tests__/gpu-scene.unit.test.ts +147 -0
- package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
- package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +92 -0
- package/src/__tests__/injection-kind-owner.test-d.ts +14 -0
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +728 -0
- package/src/__tests__/light-buffer-layout.unit.test.ts +40 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +24 -0
- package/src/__tests__/material-cooked-projection.unit.test.ts +150 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +53 -0
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +94 -0
- package/src/__tests__/material-stride-surface.unit.test.ts +32 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +106 -0
- package/src/__tests__/mesh-material-bindings.unit.test.ts +89 -0
- package/src/__tests__/mesh-stride-surface.unit.test.ts +16 -0
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +157 -0
- package/src/__tests__/morph-feature-gpu-work.integration.test.ts +80 -0
- package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
- package/src/__tests__/morph-visual-evidence.integration.test.ts +80 -0
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +19 -0
- package/src/__tests__/post-process-error-policy-owner.unit.test.ts +201 -0
- package/src/__tests__/prepared-buffer-kind-owner.test-d.ts +29 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +65 -0
- package/src/__tests__/prepared-graphics-generation.unit.test.ts +161 -0
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +138 -0
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +29 -0
- package/src/__tests__/prepared-graphics-resolver.unit.test.ts +285 -0
- package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +105 -0
- package/src/__tests__/prepared-graphics-store.unit.test.ts +154 -0
- package/src/__tests__/prepared-graphics-validation.unit.test.ts +176 -0
- package/src/__tests__/profiler-default-off.test.ts +22 -0
- package/src/__tests__/profiler-phase-catalog.test.ts +66 -0
- package/src/__tests__/profiler-phase-integration.test.ts +62 -0
- package/src/__tests__/profiler-phase-token.test.ts +79 -0
- package/src/__tests__/public-surface.test-d.ts +94 -0
- package/src/__tests__/recover-error-policy-owner.unit.test.ts +107 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +116 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +139 -0
- package/src/__tests__/render-error-exhaustive.test-d.ts +110 -0
- package/src/__tests__/render-feature-assembly.test-d.ts +43 -0
- package/src/__tests__/render-feature-context.test-d.ts +57 -0
- package/src/__tests__/render-feature-contract.test-d.ts +49 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +149 -0
- package/src/__tests__/render-feature-docs.unit.test.ts +89 -0
- package/src/__tests__/render-feature-errors.unit.test.ts +47 -0
- package/src/__tests__/render-feature-gpu-work.integration.test.ts +316 -0
- 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 +90 -0
- package/src/__tests__/render-feature-prepared-errors.test-d.ts +79 -0
- package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +80 -0
- package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +72 -0
- package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +36 -0
- package/src/__tests__/render-feature-prepared-graphics.test-d.ts +74 -0
- package/src/__tests__/render-feature-prepared-graphics.unit.test.ts +121 -0
- package/src/__tests__/render-feature-public-surface.test-d.ts +57 -0
- package/src/__tests__/render-feature-retry.unit.test.ts +87 -0
- package/src/__tests__/render-feature-scheduling.unit.test.ts +110 -0
- package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +137 -0
- package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +146 -0
- package/src/__tests__/render-feature-visibility-context.test-d.ts +33 -0
- package/src/__tests__/render-feature-visibility-context.unit.test.ts +37 -0
- package/src/__tests__/render-feature-zero-work.unit.test.ts +76 -0
- package/src/__tests__/render-graph-compute-raster-gpu.ts +342 -0
- package/src/__tests__/render-graph-compute-raster.browser.test.ts +16 -0
- package/src/__tests__/render-graph-compute-raster.dawn.test.ts +22 -0
- package/src/__tests__/render-graph-hzb-gpu.ts +239 -0
- package/src/__tests__/render-graph-hzb.browser.test.ts +16 -0
- package/src/__tests__/render-graph-hzb.dawn.test.ts +23 -0
- package/src/__tests__/render-graph-primitives.unit.test.ts +22 -0
- package/src/__tests__/render-graph-storage-indirect-gpu.ts +162 -0
- package/src/__tests__/render-graph-storage-indirect.browser.test.ts +21 -0
- package/src/__tests__/render-graph-storage-indirect.dawn.test.ts +28 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +168 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +121 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +58 -0
- package/src/__tests__/rhi-backend-package-boundary.unit.test.ts +11 -0
- package/src/__tests__/scriptable-pack-consumer.test-d.ts +14 -0
- package/src/__tests__/shader-stage-surface.unit.test.ts +43 -0
- package/src/__tests__/ssao-config.unit.test.ts +36 -0
- package/src/__tests__/ssao-kernel-surface.unit.test.ts +14 -0
- 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 +91 -0
- package/src/__tests__/texture-usage-surface.unit.test.ts +58 -0
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +223 -0
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +42 -0
- package/src/__tests__/urp-pipeline.unit.test.ts +14 -0
- package/src/__tests__/vertex-color-pipeline.unit.test.ts +132 -0
- package/src/__tests__/vertex-layout-consumer.unit.test.ts +25 -0
- package/src/__tests__/visibility-diagnostics.integration.test.ts +62 -0
- package/src/__tests__/visibility-extract.integration.test.ts +98 -0
- package/src/__tests__/visibility-extract.perf.test.ts +130 -0
- package/src/__tests__/visibility-feature-dedup.integration.test.ts +55 -0
- package/src/__tests__/visibility-hidden-report.unit.test.ts +36 -0
- package/src/__tests__/visibility-instances.integration.test.ts +46 -0
- package/src/__tests__/visibility-multi-world.integration.test.ts +86 -0
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +168 -0
- package/src/__tests__/visibility-producer-matrix.unit.test.ts +96 -0
- package/src/__tests__/visibility-public-surface.test-d.ts +27 -0
- package/src/__tests__/visibility-resolver.unit.test.ts +85 -0
- package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
- package/src/__tests__/visibility-snapshot-contract.unit.test.ts +60 -0
- package/src/__tests__/vocabulary.unit.test.ts +21 -0
- package/src/assembly/backend-contract.ts +57 -0
- package/src/assembly/factory.ts +8130 -0
- package/src/assembly/host-contract.ts +101 -0
- package/src/assembly/material/assembly.ts +48 -0
- package/src/assembly/material/pipeline-projection.ts +63 -0
- package/src/assets/asset-decoders.ts +158 -0
- package/src/assets/render-asset-port.ts +44 -0
- package/src/assets/resolve-render-asset.ts +13 -0
- package/src/authoring.ts +17 -0
- package/src/cluster-binner.ts +700 -0
- package/src/components/__tests__/points-lines-admission.unit.test.ts +219 -0
- package/src/components/__tests__/points-lines-schema.unit.test.ts +56 -0
- package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
- package/src/components/__tests__/schema-parity.unit.test.ts +25 -0
- package/src/components/__tests__/visibility-schema.unit.test.ts +35 -0
- package/src/components/camera.ts +512 -0
- package/src/components/directional-light.ts +120 -0
- package/src/components/glyph-text.ts +64 -0
- package/src/components/index.ts +54 -0
- package/src/components/instances.ts +206 -0
- package/src/components/layer.ts +69 -0
- package/src/components/light-helpers.ts +188 -0
- package/src/components/lines.ts +18 -0
- package/src/components/mesh-filter.ts +60 -0
- package/src/components/mesh-renderer.ts +61 -0
- package/src/components/point-light-shadow.ts +43 -0
- package/src/components/point-light.ts +65 -0
- package/src/components/points.ts +40 -0
- package/src/components/post-process-params.ts +35 -0
- package/src/components/scene-instance.ts +193 -0
- package/src/components/skybox-background.ts +103 -0
- package/src/components/skylight.ts +97 -0
- package/src/components/sort-key.ts +75 -0
- package/src/components/spot-light.ts +124 -0
- package/src/components/sprite-animation.ts +168 -0
- package/src/components/sprite-instances.ts +179 -0
- package/src/components/sprite-playback-mode.ts +79 -0
- package/src/components/sprite-region-override.ts +105 -0
- package/src/components/tile-layer.ts +167 -0
- package/src/components/tilemap.ts +48 -0
- package/src/components/visibility.ts +53 -0
- package/src/construct-renderer.ts +67 -0
- package/src/debug-draw-glue.ts +48 -0
- package/src/device/device-scope.ts +306 -0
- package/src/device/gpu-residency.ts +1822 -0
- package/src/device/resource-types.ts +20 -0
- package/src/engine-metrics.ts +82 -0
- package/src/errors/ecs-validation.ts +16 -0
- package/src/errors/index.ts +3 -0
- package/src/errors/recover.ts +161 -0
- package/src/errors/render.ts +1284 -0
- package/src/extract/visibility.ts +120 -0
- package/src/features/fullscreen.ts +46 -0
- package/src/features/host.ts +1363 -0
- package/src/features/morph/morph-feature.ts +377 -0
- package/src/features/plan.ts +447 -0
- package/src/features/prepared-gpu-work.ts +959 -0
- package/src/features/prepared-graphics-store.ts +449 -0
- package/src/features/prepared-graphics.ts +420 -0
- package/src/features/render-graph-compute.ts +69 -0
- package/src/features/render-graph-contribution.ts +75 -0
- package/src/features/render-graph-raster.ts +332 -0
- package/src/features/render-graph-resources.ts +38 -0
- package/src/features/targets.ts +70 -0
- package/src/features/types.ts +103 -0
- package/src/features/vocabulary.ts +24 -0
- package/src/fullscreen-post-process-pass.ts +363 -0
- package/src/glyph-text-layout-system.ts +421 -0
- package/src/gpu-driven/batch-topology.ts +245 -0
- package/src/gpu-driven/production-raster.ts +695 -0
- package/src/gpu-driven/view-gpu.ts +703 -0
- package/src/gpu-resource.ts +159 -0
- package/src/gpu-scene-schema.ts +136 -0
- package/src/gpu-scene.ts +722 -0
- package/src/gpu-stage.ts +9 -0
- package/src/gpu-texture-usage.ts +12 -0
- package/src/gpu-usage.ts +14 -0
- package/src/hdrp-buffers.ts +480 -0
- package/src/ibl/IblPipelineCache.ts +1006 -0
- package/src/ibl/skylight-bind-group.ts +513 -0
- package/src/index.ts +129 -0
- package/src/inspection-types.ts +80 -0
- package/src/instance-buffer-cache.ts +95 -0
- package/src/internal.ts +9 -0
- package/src/lifecycle.ts +168 -0
- package/src/light-buffer-layout.ts +346 -0
- package/src/materials.ts +214 -0
- package/src/mesh-material-bindings.ts +103 -0
- package/src/pbr-pipeline.ts +1137 -0
- package/src/pipeline/standard-forward-lane.ts +229 -0
- package/src/pipeline/standard-pipeline.ts +555 -0
- package/src/pipeline/standard-profile.ts +65 -0
- package/src/pipeline-builder.ts +382 -0
- package/src/pipeline-spec-types.ts +28 -0
- package/src/pipeline-spec.ts +1231 -0
- package/src/plugin.ts +69 -0
- package/src/points-lines/__tests__/bounds.unit.test.ts +21 -0
- package/src/points-lines/__tests__/cache-recovery.unit.test.ts +157 -0
- package/src/points-lines/__tests__/inspection-lanes.integration.test.ts +146 -0
- package/src/points-lines/__tests__/inspection.unit.test.ts +173 -0
- package/src/points-lines/__tests__/lane-structural.integration.test.ts +122 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +400 -0
- package/src/points-lines/__tests__/raster-lane.integration.test.ts +44 -0
- package/src/points-lines/__tests__/snapshot.unit.test.ts +101 -0
- package/src/points-lines/__tests__/view-ubo.unit.test.ts +73 -0
- package/src/points-lines/admission.ts +238 -0
- package/src/points-lines/bounds.ts +23 -0
- package/src/points-lines/expansion-cache.ts +215 -0
- package/src/points-lines/inspection.ts +97 -0
- package/src/points-lines/prepare.ts +177 -0
- package/src/points-lines/record.ts +125 -0
- package/src/points-lines/snapshot.ts +130 -0
- package/src/post-process-errors.ts +302 -0
- package/src/prepare/prepared-graphics-resolver.ts +456 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +41 -0
- package/src/record/__tests__/material-slot-plan.unit.test.ts +44 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
- package/src/record/__tests__/video-texture-view.unit.test.ts +90 -0
- package/src/record/frame-lighting.ts +1074 -0
- package/src/record/frame-snapshot.ts +500 -0
- package/src/record/frame-targets.ts +137 -0
- package/src/record/frame.ts +1598 -0
- package/src/record/helpers.ts +284 -0
- package/src/record/main-pass-geometry.ts +1065 -0
- package/src/record/main-pass-material.ts +1043 -0
- package/src/record/main-pass-sprite-draws.ts +1137 -0
- package/src/record/main-pass.ts +610 -0
- package/src/record/mesh-ssbo.ts +885 -0
- package/src/record/render-context.ts +384 -0
- package/src/record/shadow-pass.ts +698 -0
- package/src/record/skybox-post-pass.ts +593 -0
- package/src/record/typed-frame-graph.ts +461 -0
- package/src/record/view-ubo.ts +222 -0
- package/src/render-contract.ts +582 -0
- package/src/render-data.ts +385 -0
- package/src/render-graph-primitives.ts +811 -0
- package/src/render-pipeline.ts +259 -0
- package/src/render-system-extract.ts +4585 -0
- package/src/render-system.ts +1933 -0
- package/src/scene/render-scene-types.ts +67 -0
- package/src/scene/render-scene.ts +1087 -0
- package/src/scene-instances/post-spawn-resolve-joints.ts +165 -0
- package/src/shadow-atlas.ts +244 -0
- package/src/ssao-buffers.ts +334 -0
- package/src/ssao-config.ts +61 -0
- package/src/systems/active-camera.ts +116 -0
- package/src/systems/pass-selector.ts +49 -0
- package/src/systems/skin-palette-allocator.ts +251 -0
- package/src/systems/skin-palette-types.ts +14 -0
- package/src/systems/transparent-sort-config.ts +233 -0
- package/src/tilemap-chunk-extract-system.ts +1290 -0
- package/src/typed-render-graph-primitives.ts +541 -0
- package/src/typed-shadow-passes.ts +165 -0
|
@@ -0,0 +1,1074 @@
|
|
|
1
|
+
// @forgeax/engine-runtime - RenderSystem record stage: per-frame lighting.
|
|
2
|
+
// feat-20260704 M5/w31: further-split from frame.ts (AC-05 <=1500 lines/file).
|
|
3
|
+
// Pure leaf helpers invoked once each from recordFrame; behavior verbatim.
|
|
4
|
+
|
|
5
|
+
import { mat4, type Vec3, vec3 } from '@forgeax/engine-math';
|
|
6
|
+
import {
|
|
7
|
+
type BindGroup,
|
|
8
|
+
type BindGroupLayout,
|
|
9
|
+
RhiError,
|
|
10
|
+
type TextureView,
|
|
11
|
+
} from '@forgeax/engine-rhi';
|
|
12
|
+
import { toShared } from '@forgeax/engine-types';
|
|
13
|
+
import { bin, type ClusterBinProfilePhase, type ClusterBinProfileRunner } from '../cluster-binner';
|
|
14
|
+
import {
|
|
15
|
+
HdrpIndexListOverflowError,
|
|
16
|
+
HdrpLightBudgetExceededError,
|
|
17
|
+
PointShadowAtlasBoundsViolationError,
|
|
18
|
+
PointShadowAtlasUninitializedError,
|
|
19
|
+
} from '../errors/render';
|
|
20
|
+
import {
|
|
21
|
+
createHdrpClusterMembershipBindGroup,
|
|
22
|
+
createHdrpUnifiedBindGroup,
|
|
23
|
+
getOrCreateHdrpBuffers,
|
|
24
|
+
HDRP_UNIFORM_LIGHT_CAPACITY,
|
|
25
|
+
packClusterUniform,
|
|
26
|
+
} from '../hdrp-buffers';
|
|
27
|
+
import {
|
|
28
|
+
LIGHT_ARRAY_HEADER_BYTES,
|
|
29
|
+
LIGHT_ARRAY_MAX_SLOTS,
|
|
30
|
+
POINT_LIGHT_STD430_BYTES,
|
|
31
|
+
packLightArrayHeader,
|
|
32
|
+
packLightSlot,
|
|
33
|
+
packPointLight,
|
|
34
|
+
packSpotLight,
|
|
35
|
+
SPOT_LIGHT_STD430_BYTES,
|
|
36
|
+
} from '../light-buffer-layout';
|
|
37
|
+
import { DEFAULT_CLUSTER_GRID, LIGHT_INDEX_LIST_CAPACITY } from '../pipeline/standard-profile';
|
|
38
|
+
import type { CameraSnapshot, RenderHdrpClusterPhase } from '../render-contract';
|
|
39
|
+
import type {
|
|
40
|
+
DirectionalLightSnapshot,
|
|
41
|
+
ExtractedLights,
|
|
42
|
+
RenderableSnapshot,
|
|
43
|
+
SkyboxSnapshot,
|
|
44
|
+
SkylightSnapshot,
|
|
45
|
+
} from '../render-system-extract';
|
|
46
|
+
import { ShadowAtlas } from '../shadow-atlas';
|
|
47
|
+
import { getOrCreateSsaoBuffers } from '../ssao-buffers';
|
|
48
|
+
import { getSsaoParameters } from '../ssao-config';
|
|
49
|
+
import type { BindGroupCounts, RenderFrameState } from './frame-snapshot';
|
|
50
|
+
import {
|
|
51
|
+
computeProjectionMatrix,
|
|
52
|
+
computeViewMatrix,
|
|
53
|
+
isLitMaterialSnapshot,
|
|
54
|
+
warnMultiLightDirectional,
|
|
55
|
+
warnMultiLightPoint,
|
|
56
|
+
warnMultiLightSpot,
|
|
57
|
+
} from './helpers';
|
|
58
|
+
import { getOrCreateFromChain, MESH_SSBO_BYTES, MESH_UBO_FULL_ARRAY_BYTES } from './mesh-ssbo';
|
|
59
|
+
import type { PipelineState, RecordProfileRunner, RenderSystemInternals } from './render-context';
|
|
60
|
+
import { POINTS_LINES_VIEW_BYTES, VIEW_UNIFORM_BYTES } from './view-ubo';
|
|
61
|
+
|
|
62
|
+
function runHdrpClusterProfilePhase<T>(
|
|
63
|
+
runner: RecordProfileRunner | undefined,
|
|
64
|
+
phase: RenderHdrpClusterPhase,
|
|
65
|
+
action: () => T,
|
|
66
|
+
): T {
|
|
67
|
+
return runner === undefined ? action() : runner(phase, action);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* feat-20260704 M3/w18: per-frame bind-group cache resolution, extracted
|
|
72
|
+
* verbatim from `recordFrame`. Walks the handle-identity WeakMap caches
|
|
73
|
+
* (feat-20260531 M2 + feat-20260622 M3) to resolve or lazily create the view
|
|
74
|
+
* (@group 0), mesh (@group 2), and — when HDRP is active — HDRP-unified cluster
|
|
75
|
+
* bind groups. Returns all three (null when `hasValidated` is false, the Case E
|
|
76
|
+
* clear-pass-only path). No new mutable state: `bindGroupCounts` accounting +
|
|
77
|
+
* cache maps are threaded through explicitly.
|
|
78
|
+
*
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
export function buildPerFrameBindGroups(
|
|
82
|
+
internals: RenderSystemInternals,
|
|
83
|
+
frameState: RenderFrameState,
|
|
84
|
+
pipelineState: PipelineState,
|
|
85
|
+
hasValidated: boolean,
|
|
86
|
+
bindGroupCounts: BindGroupCounts,
|
|
87
|
+
graphTargets?: {
|
|
88
|
+
readonly directionalShadow?: TextureView | undefined;
|
|
89
|
+
readonly spotShadow?: TextureView | undefined;
|
|
90
|
+
},
|
|
91
|
+
includeView = true,
|
|
92
|
+
): {
|
|
93
|
+
viewBindGroup: BindGroup | null;
|
|
94
|
+
meshBindGroup: BindGroup | null;
|
|
95
|
+
hdrpClusterBindGroup: BindGroup | null;
|
|
96
|
+
hdrpClusterMembershipBindGroup: BindGroup | null;
|
|
97
|
+
} {
|
|
98
|
+
// View main (#1) chain = b0(viewUniformBuffer), b1(pointLightsBuffer),
|
|
99
|
+
// b2(spotLightsBuffer), b3(graph shadowDepth view or
|
|
100
|
+
// shadowFallbackTextureView), b4(shadowSampler), b5(atlas view), b6
|
|
101
|
+
// (shadowParams); variant 'view-main'.
|
|
102
|
+
// Mesh (#2) chain = inner b0 buffer (meshStorageBuffer.buffer); variant 'mesh'.
|
|
103
|
+
let viewBindGroup: BindGroup | null = null;
|
|
104
|
+
let meshBindGroup: BindGroup | null = null;
|
|
105
|
+
// feat-20260609-hdrp-cluster-fragment-ggx M4 / w19: HDRP unified group(2)
|
|
106
|
+
// BindGroup. Non-null when `frameState.isHdrpActive` AND HDRP buffer
|
|
107
|
+
// allocation succeeded; consumed by recordMainPass at `setBindGroup(2, ...)`.
|
|
108
|
+
let hdrpClusterBindGroup: BindGroup | null = null;
|
|
109
|
+
const hdrpClusterMembershipBindGroup: BindGroup | null = frameState.isHdrpActive
|
|
110
|
+
? frameState.hdrpClusterMembershipBindGroup
|
|
111
|
+
: null;
|
|
112
|
+
if (hasValidated) {
|
|
113
|
+
// Shadow atlas view comes from the typed graph target.
|
|
114
|
+
// Graph owns the texture lifecycle; record-stage reads the resolved
|
|
115
|
+
// view each frame (D-2 SSOT). When the graph has not allocated the
|
|
116
|
+
// target (castShadow:false or shadowMapSize=0),
|
|
117
|
+
// `getColorTargetView` returns undefined and we fall through to the
|
|
118
|
+
// 1x1 fallback view that keeps the BGL satisfied.
|
|
119
|
+
if (includeView) {
|
|
120
|
+
const shadowSampler = pipelineState.perPassResources.shadowSampler;
|
|
121
|
+
if (shadowSampler === null) {
|
|
122
|
+
return {
|
|
123
|
+
viewBindGroup: null,
|
|
124
|
+
meshBindGroup: null,
|
|
125
|
+
hdrpClusterBindGroup: null,
|
|
126
|
+
hdrpClusterMembershipBindGroup,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const graphShadowView = graphTargets?.directionalShadow;
|
|
130
|
+
const b3View =
|
|
131
|
+
graphShadowView !== undefined ? graphShadowView : pipelineState.shadowFallbackTextureView;
|
|
132
|
+
// feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: bind the real
|
|
133
|
+
// ShadowAtlas cube_array view when point shadows are active in this
|
|
134
|
+
// frame; otherwise the 1x1x6 fallback (cleared to 1.0 = fully lit).
|
|
135
|
+
const pointShadowAtlas = frameState.pointShadowAtlas;
|
|
136
|
+
const atlasViewMaybe = pointShadowAtlas?.isAllocated()
|
|
137
|
+
? pointShadowAtlas.getAtlasView()
|
|
138
|
+
: null;
|
|
139
|
+
const b5View =
|
|
140
|
+
atlasViewMaybe !== null ? atlasViewMaybe : pipelineState.shadowAtlasFallbackTextureView;
|
|
141
|
+
// feat-20260625-spot-light-shadow-mapping M2 / w21 (D-1 fragment side +
|
|
142
|
+
// D-5): bind the real `spotShadowDepth` 2D atlas view (graph-owned) when
|
|
143
|
+
// spot shadows run this frame; otherwise the 1x1 depth fallback cleared to
|
|
144
|
+
// 1.0 (fully lit) — same `texture_depth_2d` shape as binding 3, so it
|
|
145
|
+
// satisfies the BGL without a dedicated spot fallback allocation. binding
|
|
146
|
+
// 9 always binds the real spotLightViewProj UBO (zeroed lanes are safe via
|
|
147
|
+
// the shadowAtlasTile >= 0 shader gate).
|
|
148
|
+
const graphSpotShadowView = graphTargets?.spotShadow;
|
|
149
|
+
const b8View =
|
|
150
|
+
graphSpotShadowView !== undefined
|
|
151
|
+
? graphSpotShadowView
|
|
152
|
+
: pipelineState.shadowFallbackTextureView;
|
|
153
|
+
viewBindGroup = getOrCreateFromChain(
|
|
154
|
+
frameState.viewBindGroupCache,
|
|
155
|
+
[
|
|
156
|
+
pipelineState.viewUniformBuffer,
|
|
157
|
+
pipelineState.pointLightsBuffer,
|
|
158
|
+
pipelineState.spotLightsBuffer,
|
|
159
|
+
b3View,
|
|
160
|
+
shadowSampler,
|
|
161
|
+
b5View,
|
|
162
|
+
pipelineState.shadowParamsBuffer,
|
|
163
|
+
b8View,
|
|
164
|
+
pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
|
|
165
|
+
],
|
|
166
|
+
'view-main',
|
|
167
|
+
() => {
|
|
168
|
+
const viewBindGroupResult = internals.device.createBindGroup({
|
|
169
|
+
label: 'pbr-view-bg',
|
|
170
|
+
layout: pipelineState.viewBindGroupLayout,
|
|
171
|
+
entries: [
|
|
172
|
+
{
|
|
173
|
+
binding: 0,
|
|
174
|
+
resource: {
|
|
175
|
+
kind: 'buffer',
|
|
176
|
+
value: { buffer: pipelineState.viewUniformBuffer, size: VIEW_UNIFORM_BYTES },
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
binding: 1,
|
|
181
|
+
resource: {
|
|
182
|
+
kind: 'buffer',
|
|
183
|
+
value: { buffer: pipelineState.pointLightsBuffer },
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
binding: 2,
|
|
188
|
+
resource: {
|
|
189
|
+
kind: 'buffer',
|
|
190
|
+
value: { buffer: pipelineState.spotLightsBuffer },
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
binding: 3,
|
|
195
|
+
resource: {
|
|
196
|
+
kind: 'textureView',
|
|
197
|
+
value: b3View,
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
binding: 4,
|
|
202
|
+
resource: {
|
|
203
|
+
kind: 'sampler',
|
|
204
|
+
value: shadowSampler,
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
// feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1:
|
|
208
|
+
// cube_array shadow atlas view (real ShadowAtlas when point
|
|
209
|
+
// shadows are active; else 1x1x6 fallback).
|
|
210
|
+
{
|
|
211
|
+
binding: 5,
|
|
212
|
+
resource: {
|
|
213
|
+
kind: 'textureView',
|
|
214
|
+
value: b5View,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
// feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1:
|
|
218
|
+
// shadowParams UBO (`array<vec4<f32>, 4>` = 64 B). Lane N
|
|
219
|
+
// stores `(near, far, 1/(far-near), 0)` for the point light
|
|
220
|
+
// with shadowAtlasLayer === N. Updated per frame from
|
|
221
|
+
// `pointShadowSnapshots` below.
|
|
222
|
+
{
|
|
223
|
+
binding: 6,
|
|
224
|
+
resource: {
|
|
225
|
+
kind: 'buffer',
|
|
226
|
+
value: { buffer: pipelineState.shadowParamsBuffer },
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
// feat-20260613-csm-cascaded-shadow-maps M5 / w28 (rebased to
|
|
230
|
+
// binding 7 on 2026-06-13 to make room for point-shadow 5/6):
|
|
231
|
+
// forward shaders declare binding 7 in common.wgsl (shared
|
|
232
|
+
// view BGL) but never reference it; only shadow_caster.wgsl
|
|
233
|
+
// reads it. Host writes a stable singleton buffer so every
|
|
234
|
+
// forward bind group entry stays populated.
|
|
235
|
+
{
|
|
236
|
+
binding: 7,
|
|
237
|
+
resource: {
|
|
238
|
+
kind: 'buffer',
|
|
239
|
+
value: { buffer: pipelineState.shadowCasterCascadeBuffer },
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
// feat-20260625-spot-light-shadow-mapping M3 / w21 (D-5):
|
|
243
|
+
// spot shadow 2D atlas (real spotShadowDepth view when spot
|
|
244
|
+
// shadows run this frame, else the 1x1 depth fallback). Always-on.
|
|
245
|
+
{
|
|
246
|
+
binding: 8,
|
|
247
|
+
resource: {
|
|
248
|
+
kind: 'textureView',
|
|
249
|
+
value: b8View,
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
binding: 10,
|
|
254
|
+
resource: {
|
|
255
|
+
kind: 'buffer',
|
|
256
|
+
value: {
|
|
257
|
+
buffer: pipelineState.pointsLinesViewBuffer ?? pipelineState.viewUniformBuffer,
|
|
258
|
+
size: POINTS_LINES_VIEW_BYTES,
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
// feat-20260625-spot-light-shadow-mapping w25: the per-spot
|
|
263
|
+
// fragment-read lightViewProj matrices fold into the View UBO
|
|
264
|
+
// (binding 0, `view.spotLightViewProj`) — no standalone binding 9
|
|
265
|
+
// (WebGL2 fragment uniform-buffer budget). binding 10 is the
|
|
266
|
+
// dedicated vertex-only Points/Lines viewport UBO.
|
|
267
|
+
],
|
|
268
|
+
});
|
|
269
|
+
if (!viewBindGroupResult.ok) throw viewBindGroupResult.error;
|
|
270
|
+
return viewBindGroupResult.value;
|
|
271
|
+
},
|
|
272
|
+
bindGroupCounts,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// M3 / w10 (D-3 hard constraint): use the inner `.buffer` as the
|
|
277
|
+
// WeakMap chain key so the cache tracks the underlying GPU buffer
|
|
278
|
+
// identity. The wrapper object's identity is stable across grow
|
|
279
|
+
// events; using the wrapper would defeat AC-07 cache invalidation.
|
|
280
|
+
meshBindGroup = getOrCreateFromChain(
|
|
281
|
+
frameState.meshBindGroupCache,
|
|
282
|
+
[pipelineState.meshStorageBuffer.buffer],
|
|
283
|
+
'mesh',
|
|
284
|
+
() => {
|
|
285
|
+
// bug-20260610: WebGL2 fallback path needs the binding to cover the
|
|
286
|
+
// whole `array<Mesh, 128>` uniform buffer (14336 B) instead of a
|
|
287
|
+
// single dynamic-offset slot (112 B). `caps.storageBuffer === false`
|
|
288
|
+
// is the same proxy createRenderer uses to pick the uniform variant.
|
|
289
|
+
const meshBindSize = internals.device.caps.storageBuffer
|
|
290
|
+
? MESH_SSBO_BYTES
|
|
291
|
+
: MESH_UBO_FULL_ARRAY_BYTES;
|
|
292
|
+
const meshBindGroupResult = internals.device.createBindGroup({
|
|
293
|
+
label: 'pbr-mesh-bg',
|
|
294
|
+
layout: pipelineState.meshBindGroupLayout,
|
|
295
|
+
entries: [
|
|
296
|
+
{
|
|
297
|
+
binding: 0,
|
|
298
|
+
resource: {
|
|
299
|
+
kind: 'buffer',
|
|
300
|
+
value: {
|
|
301
|
+
buffer: pipelineState.meshStorageBuffer.buffer,
|
|
302
|
+
offset: 0,
|
|
303
|
+
size: meshBindSize,
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
});
|
|
309
|
+
if (!meshBindGroupResult.ok) throw meshBindGroupResult.error;
|
|
310
|
+
return meshBindGroupResult.value;
|
|
311
|
+
},
|
|
312
|
+
bindGroupCounts,
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// feat-20260609-hdrp-cluster-fragment-ggx M4 / w19: when HDRP is active,
|
|
316
|
+
// build the unified group(2) BindGroup that carries the mesh SSBO at
|
|
317
|
+
// binding 0 + the 4 cluster buffers at bindings 3..6. The bindGroup
|
|
318
|
+
// shares the mesh SSBO with URP's `meshBindGroup` (same `meshStorageBuffer.buffer`
|
|
319
|
+
// + same per-entity stride), so the dynamic offset issued at
|
|
320
|
+
// `setBindGroup(2, ...)` covers binding 0 of either layout. Cached
|
|
321
|
+
// alongside `meshBindGroupCache` keyed on the mesh SSBO + cluster
|
|
322
|
+
// buffer identities; cache invalidates on a buffer-grow event the same
|
|
323
|
+
// way the mesh path does (handle id rotation).
|
|
324
|
+
if (frameState.isHdrpActive) {
|
|
325
|
+
const hdrpBuffers = getOrCreateHdrpBuffers(
|
|
326
|
+
internals,
|
|
327
|
+
frameState.installedPipelineConfig?.clusterGrid,
|
|
328
|
+
);
|
|
329
|
+
if (hdrpBuffers !== null) {
|
|
330
|
+
// D-3: buffer dimension uses the inner `.buffer` (same constraint
|
|
331
|
+
// as the mesh path) so a grow event rotates the chain key.
|
|
332
|
+
hdrpClusterBindGroup = getOrCreateFromChain(
|
|
333
|
+
frameState.meshBindGroupCache,
|
|
334
|
+
[
|
|
335
|
+
pipelineState.meshStorageBuffer.buffer,
|
|
336
|
+
hdrpBuffers.lightDataBuffer,
|
|
337
|
+
hdrpBuffers.clusterGridBuffer,
|
|
338
|
+
hdrpBuffers.lightIndexListBuffer,
|
|
339
|
+
hdrpBuffers.clusterUniformBuffer,
|
|
340
|
+
],
|
|
341
|
+
'hdrp-unified',
|
|
342
|
+
() => {
|
|
343
|
+
const bg = createHdrpUnifiedBindGroup(
|
|
344
|
+
internals,
|
|
345
|
+
hdrpBuffers,
|
|
346
|
+
pipelineState.meshStorageBuffer.buffer,
|
|
347
|
+
);
|
|
348
|
+
if (bg === null) {
|
|
349
|
+
throw new RhiError({
|
|
350
|
+
code: 'webgpu-runtime-error',
|
|
351
|
+
expected: 'HDRP unified BindGroup creation succeeds when HDRP is active',
|
|
352
|
+
hint: 'inspect prior errorRegistry events for createBindGroup failure detail',
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
return bg;
|
|
356
|
+
},
|
|
357
|
+
bindGroupCounts,
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return { viewBindGroup, meshBindGroup, hdrpClusterBindGroup, hdrpClusterMembershipBindGroup };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* feat-20260704 M3/w18: per-frame lighting preparation, extracted verbatim from
|
|
367
|
+
* `recordFrame`. (1) URP-only multi-light warn-once (directional / point / spot
|
|
368
|
+
* over `LIGHT_ARRAY_MAX_SLOTS`; HDRP gated off — 256 SSBO lights). (2) pin the
|
|
369
|
+
* point + spot shadow snapshot lists onto frameState for the URP shadow caster
|
|
370
|
+
* pass closures + lazy-allocate the point-shadow cube_array atlas on first
|
|
371
|
+
* non-empty frame (AC-09 zero-shadow zero-alloc). (3) destructure ExtractedLights
|
|
372
|
+
* into the directional-fallback `light` (zero-intensity Case C default), point /
|
|
373
|
+
* spot arrays, and totalLightCount.
|
|
374
|
+
*
|
|
375
|
+
* @internal
|
|
376
|
+
*/
|
|
377
|
+
export function prepareFrameLighting(
|
|
378
|
+
internals: RenderSystemInternals,
|
|
379
|
+
frameState: RenderFrameState,
|
|
380
|
+
lights: ExtractedLights,
|
|
381
|
+
): {
|
|
382
|
+
light: DirectionalLightSnapshot;
|
|
383
|
+
pointLights: ExtractedLights['point'];
|
|
384
|
+
spotLights: ExtractedLights['spot'];
|
|
385
|
+
totalLightCount: number;
|
|
386
|
+
} {
|
|
387
|
+
if (lights.directionalCount > 1) {
|
|
388
|
+
warnMultiLightDirectional(frameState, lights.directionalCount);
|
|
389
|
+
}
|
|
390
|
+
// feat-20260621-merge-directionallightshadow-into-directionallight M3 / m3-t2:
|
|
391
|
+
// the AC-04/AC-22 "shadow disabled by missing component" once-warn is gone.
|
|
392
|
+
// After merging DirectionalLightShadow into DirectionalLight there is no
|
|
393
|
+
// orphan-shadow / missing-companion configuration to warn about -- castShadow
|
|
394
|
+
// defaults true on the single component, so the warn condition can never
|
|
395
|
+
// arise. The error class + RuntimeErrorCode member have been removed in M4 (m4-t2).
|
|
396
|
+
|
|
397
|
+
// feat-20260608-cluster-lighting M6 / w23 (F-4 fix): URP-only multi-light
|
|
398
|
+
// warn. HDRP supports 256 punctual lights via SSBO; the 4-slot first-slice
|
|
399
|
+
// cap is irrelevant under HDRP, so gate on `!isHdrpActive` to silence noise.
|
|
400
|
+
// Sibling tweak-20260608-rhi-hdr-renderable-caps-and-warn-once (#320)
|
|
401
|
+
// extracted the warn into warnMultiLight{Point,Spot} helpers (warn-once
|
|
402
|
+
// dedup); we keep the helpers and add the HDRP gate on top.
|
|
403
|
+
if (!frameState.isHdrpActive) {
|
|
404
|
+
if (lights.point.length > LIGHT_ARRAY_MAX_SLOTS) {
|
|
405
|
+
warnMultiLightPoint(frameState, lights.point.length);
|
|
406
|
+
}
|
|
407
|
+
if (lights.spot.length > LIGHT_ARRAY_MAX_SLOTS) {
|
|
408
|
+
warnMultiLightSpot(frameState, lights.spot.length);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// feat-20260612-point-light-shadows-urp-hdrp M3 / T-M3-2 (plan-strategy §D-1):
|
|
413
|
+
// project lights.pointShadow onto frameState so the URP point shadow caster
|
|
414
|
+
// pass can read the snapshot list during graph execute. Lazy-allocate the
|
|
415
|
+
// cube_array atlas on first non-empty frame; zero-shadow scenes never
|
|
416
|
+
// touch the GPU here (AC-09). The snapshot list is stable for the
|
|
417
|
+
// duration of recordFrame; its count is part of the typed topology key.
|
|
418
|
+
frameState.pointShadowSnapshots = lights.pointShadow;
|
|
419
|
+
// feat-20260625-spot-light-shadow-mapping M2 / w9 (D-2): pin the spot
|
|
420
|
+
// snapshots for the spotShadowDepth caster pass closure. The spot atlas is
|
|
421
|
+
// a graph-owned typed target, not a runtime ShadowAtlas, so graph compilation
|
|
422
|
+
// owns the depth texture lifetime.
|
|
423
|
+
frameState.spotShadowSnapshots = lights.spot;
|
|
424
|
+
if (lights.pointShadow.length > 0) {
|
|
425
|
+
if (frameState.pointShadowAtlas === null) {
|
|
426
|
+
const firstSnap = lights.pointShadow[0];
|
|
427
|
+
const faceSize = firstSnap?.mapSize ?? 512;
|
|
428
|
+
frameState.pointShadowAtlas = new ShadowAtlas(internals.device, {
|
|
429
|
+
faceSize,
|
|
430
|
+
layers: 4,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
try {
|
|
434
|
+
frameState.pointShadowAtlas.ensure();
|
|
435
|
+
} catch (e) {
|
|
436
|
+
if (
|
|
437
|
+
e instanceof PointShadowAtlasUninitializedError ||
|
|
438
|
+
e instanceof PointShadowAtlasBoundsViolationError
|
|
439
|
+
) {
|
|
440
|
+
internals.errorRegistry.fire(e);
|
|
441
|
+
} else {
|
|
442
|
+
throw e;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// ExtractedLights three-arm consumption (R-10 preparation; M2 / w16):
|
|
448
|
+
//
|
|
449
|
+
// - lights.directional : feeds the View UBO at slot [16..23]
|
|
450
|
+
// (lightDir + lightColor; existing path).
|
|
451
|
+
// - lights.point[] : packed into pointLightsBuffer (std430).
|
|
452
|
+
// - lights.spot[] : packed into spotLightsBuffer (std430).
|
|
453
|
+
//
|
|
454
|
+
// Each variant carries the discriminant `kind` so the record-time packing
|
|
455
|
+
// call sites can run exhaustive switch (charter P2 + AC-03).
|
|
456
|
+
const directionalLight: DirectionalLightSnapshot | undefined = lights.directional;
|
|
457
|
+
const pointLights = lights.point;
|
|
458
|
+
const spotLights = lights.spot;
|
|
459
|
+
|
|
460
|
+
// Case C: 0 DirectionalLight = legitimate scene; the View UBO falls
|
|
461
|
+
// back to a zero-intensity directional payload so the shader's
|
|
462
|
+
// `view.lightDir * view.lightColor` term contributes nothing
|
|
463
|
+
// (physically-correct black under standard, untouched under unlit).
|
|
464
|
+
const light: DirectionalLightSnapshot = directionalLight ?? {
|
|
465
|
+
kind: 'directional' as const,
|
|
466
|
+
direction: vec3.create(0, -1, 0),
|
|
467
|
+
color: vec3.create(0, 0, 0),
|
|
468
|
+
intensity: 0,
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
const totalLightCount =
|
|
472
|
+
(directionalLight !== undefined ? 1 : 0) + pointLights.length + spotLights.length;
|
|
473
|
+
|
|
474
|
+
return { light, pointLights, spotLights, totalLightCount };
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* feat-20260704 M3/w18: per-frame full rewrite of the PointLight + SpotLight
|
|
479
|
+
* std430 storage buffers, extracted verbatim from `recordFrame`.
|
|
480
|
+
*
|
|
481
|
+
* feat-20260519-light-casters-point-spot-pbr M3 / w20 (D-S1 + D-S2 + D-S6):
|
|
482
|
+
* header (16 B count u32 + 12 B pad) at offset 0 + first-slice cap N=4 slots
|
|
483
|
+
* packed sequentially. The N>4 fail-fast upstream ensures the counts are <= 4
|
|
484
|
+
* when the listener registry consumed the structured error; the slice keeps
|
|
485
|
+
* the buffer write bounded even if downstream listeners ignore the RhiError
|
|
486
|
+
* (charter P9 graceful degradation: surplus entities dropped, frame records).
|
|
487
|
+
*
|
|
488
|
+
* @internal
|
|
489
|
+
*/
|
|
490
|
+
export function writePointSpotLightBuffers(
|
|
491
|
+
internals: RenderSystemInternals,
|
|
492
|
+
pipelineState: PipelineState,
|
|
493
|
+
lights: ExtractedLights,
|
|
494
|
+
): void {
|
|
495
|
+
const pointSlots =
|
|
496
|
+
lights.point.length <= LIGHT_ARRAY_MAX_SLOTS
|
|
497
|
+
? lights.point
|
|
498
|
+
: lights.point.slice(0, LIGHT_ARRAY_MAX_SLOTS);
|
|
499
|
+
const pointHeader = packLightArrayHeader(pointSlots.length);
|
|
500
|
+
const pointHeaderUpload = internals.device.queue.writeBuffer(
|
|
501
|
+
pipelineState.pointLightsBuffer,
|
|
502
|
+
0,
|
|
503
|
+
new Uint8Array(pointHeader),
|
|
504
|
+
);
|
|
505
|
+
if (!pointHeaderUpload.ok) throw pointHeaderUpload.error;
|
|
506
|
+
for (let i = 0; i < pointSlots.length; i++) {
|
|
507
|
+
const slot = pointSlots[i];
|
|
508
|
+
if (slot === undefined) continue;
|
|
509
|
+
const packed = packPointLight(slot);
|
|
510
|
+
const offset = LIGHT_ARRAY_HEADER_BYTES + i * POINT_LIGHT_STD430_BYTES;
|
|
511
|
+
const writeRes = internals.device.queue.writeBuffer(
|
|
512
|
+
pipelineState.pointLightsBuffer,
|
|
513
|
+
offset,
|
|
514
|
+
packed,
|
|
515
|
+
);
|
|
516
|
+
if (!writeRes.ok) throw writeRes.error;
|
|
517
|
+
}
|
|
518
|
+
const spotSlots =
|
|
519
|
+
lights.spot.length <= LIGHT_ARRAY_MAX_SLOTS
|
|
520
|
+
? lights.spot
|
|
521
|
+
: lights.spot.slice(0, LIGHT_ARRAY_MAX_SLOTS);
|
|
522
|
+
const spotHeader = packLightArrayHeader(spotSlots.length);
|
|
523
|
+
const spotHeaderUpload = internals.device.queue.writeBuffer(
|
|
524
|
+
pipelineState.spotLightsBuffer,
|
|
525
|
+
0,
|
|
526
|
+
new Uint8Array(spotHeader),
|
|
527
|
+
);
|
|
528
|
+
if (!spotHeaderUpload.ok) throw spotHeaderUpload.error;
|
|
529
|
+
for (let i = 0; i < spotSlots.length; i++) {
|
|
530
|
+
const slot = spotSlots[i];
|
|
531
|
+
if (slot === undefined) continue;
|
|
532
|
+
const packed = packSpotLight(slot);
|
|
533
|
+
const offset = LIGHT_ARRAY_HEADER_BYTES + i * SPOT_LIGHT_STD430_BYTES;
|
|
534
|
+
const writeRes = internals.device.queue.writeBuffer(
|
|
535
|
+
pipelineState.spotLightsBuffer,
|
|
536
|
+
offset,
|
|
537
|
+
packed,
|
|
538
|
+
);
|
|
539
|
+
if (!writeRes.ok) throw writeRes.error;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* feat-20260704 M3/w18: write the point-shadow params UBO (bound at viewBg
|
|
545
|
+
* binding 6), extracted verbatim from `recordFrame`.
|
|
546
|
+
*
|
|
547
|
+
* feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: 4 lanes x vec4<f32>;
|
|
548
|
+
* lane[shadowAtlasLayer] = (near, far, 1/(far-near), 0). Lanes for non-shadow
|
|
549
|
+
* slots stay zero (the WGSL sample path is gated by PointLight.shadowAtlasLayer
|
|
550
|
+
* >= 0). Always writes the full 64 B so stale non-zero lanes from a previous
|
|
551
|
+
* frame's allocation cannot poison the current frame.
|
|
552
|
+
*
|
|
553
|
+
* @internal
|
|
554
|
+
*/
|
|
555
|
+
export function writeShadowParamsBuffer(
|
|
556
|
+
internals: RenderSystemInternals,
|
|
557
|
+
frameState: RenderFrameState,
|
|
558
|
+
pipelineState: PipelineState,
|
|
559
|
+
): void {
|
|
560
|
+
const SHADOW_PARAMS_LANE_COUNT = 4;
|
|
561
|
+
const SHADOW_PARAMS_FLOATS_PER_LANE = 4;
|
|
562
|
+
const shadowParamsArr = new Float32Array(
|
|
563
|
+
SHADOW_PARAMS_LANE_COUNT * SHADOW_PARAMS_FLOATS_PER_LANE,
|
|
564
|
+
);
|
|
565
|
+
for (let i = 0; i < frameState.pointShadowSnapshots.length; i++) {
|
|
566
|
+
const ps = frameState.pointShadowSnapshots[i];
|
|
567
|
+
if (ps === undefined) continue;
|
|
568
|
+
const layer = ps.shadowAtlasLayer;
|
|
569
|
+
if (layer < 0 || layer >= SHADOW_PARAMS_LANE_COUNT) continue;
|
|
570
|
+
const base = layer * SHADOW_PARAMS_FLOATS_PER_LANE;
|
|
571
|
+
const near = ps.nearPlane;
|
|
572
|
+
const far = ps.farPlane;
|
|
573
|
+
const invSpan = far > near ? 1 / (far - near) : 0;
|
|
574
|
+
shadowParamsArr[base] = near;
|
|
575
|
+
shadowParamsArr[base + 1] = far;
|
|
576
|
+
shadowParamsArr[base + 2] = invSpan;
|
|
577
|
+
shadowParamsArr[base + 3] = 0;
|
|
578
|
+
}
|
|
579
|
+
const shadowParamsWriteRes = internals.device.queue.writeBuffer(
|
|
580
|
+
pipelineState.shadowParamsBuffer,
|
|
581
|
+
0,
|
|
582
|
+
shadowParamsArr,
|
|
583
|
+
);
|
|
584
|
+
if (!shadowParamsWriteRes.ok) {
|
|
585
|
+
internals.errorRegistry.fire(shadowParamsWriteRes.error);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* feat-20260704 M3/w18: zero-light standard-material once-warn, extracted
|
|
591
|
+
* verbatim from `recordFrame`.
|
|
592
|
+
*
|
|
593
|
+
* feat-20260520-skylight-ibl-cubemap M4 / t27 (AC-10): fires once per
|
|
594
|
+
* RenderSystem lifetime when the 0-light three-condition conjunction holds — no
|
|
595
|
+
* Skylight, 0 direct light (totalLightCount === 0), AND at least one builtin
|
|
596
|
+
* standard/PBR material (which renders black with no light). Custom shaders
|
|
597
|
+
* own their lighting contract and cannot be classified by this generic
|
|
598
|
+
* diagnostic. Suppressed under NODE_ENV=production.
|
|
599
|
+
*
|
|
600
|
+
* @internal
|
|
601
|
+
*/
|
|
602
|
+
export function warnZeroLightStandard(
|
|
603
|
+
frameState: RenderFrameState,
|
|
604
|
+
renderables: readonly RenderableSnapshot[],
|
|
605
|
+
skylight: SkylightSnapshot | undefined,
|
|
606
|
+
totalLightCount: number,
|
|
607
|
+
): void {
|
|
608
|
+
const hasStandardMaterial = renderables.some((r) => isLitMaterialSnapshot(r.material));
|
|
609
|
+
if (
|
|
610
|
+
skylight === undefined &&
|
|
611
|
+
totalLightCount === 0 &&
|
|
612
|
+
hasStandardMaterial &&
|
|
613
|
+
!frameState.warnedZeroLightStandard
|
|
614
|
+
) {
|
|
615
|
+
frameState.warnedZeroLightStandard = true;
|
|
616
|
+
const env = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process;
|
|
617
|
+
if (env?.env?.NODE_ENV !== 'production') {
|
|
618
|
+
console.warn(
|
|
619
|
+
'[forgeax] standard material renders black with 0 lights of every type (no Skylight, and directional + point + spot all empty); spawn at least one light (Skylight, DirectionalLight, PointLight, or SpotLight) or switch material to an unlit shader (Materials.unlit(...)). See AGENTS.md section Breaking changes 2026-05-19.',
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* feat-20260704 M3/w18: HDRP per-frame CPU cluster binning + light-data /
|
|
627
|
+
* cluster-grid / light-index-list / cluster-uniform / SSAO uniform buffer
|
|
628
|
+
* uploads. Extracted verbatim from `recordFrame`. Runs only when the HDRP
|
|
629
|
+
* pipeline is active. A zero-punctual frame explicitly clears the persistent
|
|
630
|
+
* cluster buffers so stale membership cannot leak across frames; direct and
|
|
631
|
+
* non-clustered paths remain untouched.
|
|
632
|
+
*
|
|
633
|
+
* feat-20260608-cluster-lighting M5 / w21 + M6 / w23 + r2 fix-up: fail-soft
|
|
634
|
+
* semantics preserved verbatim — index-list-overflow and light-budget-exceeded
|
|
635
|
+
* fire once per frame (via `frameState.hdrpOncePerFrameFired`) and continue
|
|
636
|
+
* rendering.
|
|
637
|
+
*
|
|
638
|
+
* @internal
|
|
639
|
+
*/
|
|
640
|
+
export function writeHdrpClusterAndSsaoBuffers(
|
|
641
|
+
internals: RenderSystemInternals,
|
|
642
|
+
frameState: RenderFrameState,
|
|
643
|
+
camera: CameraSnapshot,
|
|
644
|
+
pointLights: ExtractedLights['point'],
|
|
645
|
+
spotLights: ExtractedLights['spot'],
|
|
646
|
+
profilePhase?: RecordProfileRunner,
|
|
647
|
+
useGpuMembership = false,
|
|
648
|
+
membershipBindGroupLayout: BindGroupLayout | null = null,
|
|
649
|
+
): void {
|
|
650
|
+
const hdrpLightCount = pointLights.length + spotLights.length;
|
|
651
|
+
if (!frameState.isHdrpActive) return;
|
|
652
|
+
if (hdrpLightCount === 0) {
|
|
653
|
+
const grid = frameState.installedPipelineConfig?.clusterGrid ?? DEFAULT_CLUSTER_GRID;
|
|
654
|
+
const hdrpBuffers = getOrCreateHdrpBuffers(internals, grid);
|
|
655
|
+
if (hdrpBuffers === null) return;
|
|
656
|
+
const lightCapacity = hdrpBuffers.storageBuffer ? 256 : HDRP_UNIFORM_LIGHT_CAPACITY;
|
|
657
|
+
const clusterSsaoConfig = frameState.installedPipelineConfig?.ssao;
|
|
658
|
+
const clusterSsaoIntensity =
|
|
659
|
+
clusterSsaoConfig !== undefined && clusterSsaoConfig.enabled === true
|
|
660
|
+
? (clusterSsaoConfig.intensity ?? 1.0)
|
|
661
|
+
: 0;
|
|
662
|
+
const clusterUniformPayload = packClusterUniform(
|
|
663
|
+
grid,
|
|
664
|
+
camera.near,
|
|
665
|
+
camera.far,
|
|
666
|
+
clusterSsaoIntensity,
|
|
667
|
+
0,
|
|
668
|
+
lightCapacity,
|
|
669
|
+
);
|
|
670
|
+
const clusterUniformUpload = internals.device.queue.writeBuffer(
|
|
671
|
+
hdrpBuffers.clusterUniformBuffer,
|
|
672
|
+
0,
|
|
673
|
+
new Uint8Array(clusterUniformPayload),
|
|
674
|
+
);
|
|
675
|
+
if (!clusterUniformUpload.ok) internals.errorRegistry.fire(clusterUniformUpload.error);
|
|
676
|
+
const clusterGridClear = internals.device.queue.writeBuffer(
|
|
677
|
+
hdrpBuffers.clusterGridBuffer,
|
|
678
|
+
0,
|
|
679
|
+
new Uint8Array(hdrpBuffers.clusterGridBytes),
|
|
680
|
+
);
|
|
681
|
+
if (!clusterGridClear.ok) internals.errorRegistry.fire(clusterGridClear.error);
|
|
682
|
+
const lightIndexListClear = internals.device.queue.writeBuffer(
|
|
683
|
+
hdrpBuffers.lightIndexListBuffer,
|
|
684
|
+
0,
|
|
685
|
+
new Uint8Array(hdrpBuffers.lightIndexListBytes),
|
|
686
|
+
);
|
|
687
|
+
if (!lightIndexListClear.ok) internals.errorRegistry.fire(lightIndexListClear.error);
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
const HDRP_LIGHT_BUDGET = 256;
|
|
691
|
+
let effectivePointLights = pointLights;
|
|
692
|
+
let effectiveSpotLights = spotLights;
|
|
693
|
+
if (hdrpLightCount > HDRP_LIGHT_BUDGET) {
|
|
694
|
+
if (!frameState.hdrpOncePerFrameFired.has('hdrp-light-budget-exceeded')) {
|
|
695
|
+
frameState.hdrpOncePerFrameFired.add('hdrp-light-budget-exceeded');
|
|
696
|
+
internals.errorRegistry.fire(
|
|
697
|
+
new HdrpLightBudgetExceededError(hdrpLightCount, HDRP_LIGHT_BUDGET),
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
if (pointLights.length >= HDRP_LIGHT_BUDGET) {
|
|
701
|
+
effectivePointLights = pointLights.slice(0, HDRP_LIGHT_BUDGET);
|
|
702
|
+
effectiveSpotLights = [];
|
|
703
|
+
} else {
|
|
704
|
+
effectivePointLights = pointLights;
|
|
705
|
+
effectiveSpotLights = spotLights.slice(0, HDRP_LIGHT_BUDGET - pointLights.length);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
const effectiveLightCount = effectivePointLights.length + effectiveSpotLights.length;
|
|
709
|
+
const configuredClusterGrid =
|
|
710
|
+
frameState.installedPipelineConfig?.clusterGrid ?? DEFAULT_CLUSTER_GRID;
|
|
711
|
+
let gpuMembership = useGpuMembership && membershipBindGroupLayout !== null;
|
|
712
|
+
if (
|
|
713
|
+
gpuMembership &&
|
|
714
|
+
membershipBindGroupLayout !== null &&
|
|
715
|
+
frameState.hdrpClusterMembershipBindGroup === null
|
|
716
|
+
) {
|
|
717
|
+
const hdrpBuffers = getOrCreateHdrpBuffers(internals, configuredClusterGrid);
|
|
718
|
+
if (hdrpBuffers !== null) {
|
|
719
|
+
frameState.hdrpClusterMembershipBindGroup = createHdrpClusterMembershipBindGroup(
|
|
720
|
+
internals,
|
|
721
|
+
hdrpBuffers,
|
|
722
|
+
membershipBindGroupLayout,
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
gpuMembership = frameState.hdrpClusterMembershipBindGroup !== null;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
const { clusterGrid, gridX, gridY, gridZ, clusterGridBuf, lightIndexListBuf, lightIndexCount } =
|
|
729
|
+
runHdrpClusterProfilePhase(profilePhase, 'record/scene-state/hdrp-cluster/binner', () => {
|
|
730
|
+
const binnerProfile: ClusterBinProfileRunner | undefined =
|
|
731
|
+
profilePhase === undefined
|
|
732
|
+
? undefined
|
|
733
|
+
: <T>(phase: ClusterBinProfilePhase, action: () => T): T =>
|
|
734
|
+
runHdrpClusterProfilePhase(
|
|
735
|
+
profilePhase,
|
|
736
|
+
`record/scene-state/hdrp-cluster/binner/${phase}` as RenderHdrpClusterPhase,
|
|
737
|
+
action,
|
|
738
|
+
);
|
|
739
|
+
const {
|
|
740
|
+
hdrpLights,
|
|
741
|
+
clusterGrid,
|
|
742
|
+
gridX,
|
|
743
|
+
gridY,
|
|
744
|
+
gridZ,
|
|
745
|
+
clusterGridBuf,
|
|
746
|
+
lightIndexListBuf,
|
|
747
|
+
projMatrix,
|
|
748
|
+
viewMatrix,
|
|
749
|
+
} = runHdrpClusterProfilePhase(
|
|
750
|
+
profilePhase,
|
|
751
|
+
'record/scene-state/hdrp-cluster/binner/input-preparation',
|
|
752
|
+
() => {
|
|
753
|
+
const hdrpLights: Array<{ position: Vec3; range: number }> = [];
|
|
754
|
+
for (const pl of effectivePointLights) {
|
|
755
|
+
const range =
|
|
756
|
+
Number.isFinite(pl.invRangeSquared) && pl.invRangeSquared > 0
|
|
757
|
+
? Math.sqrt(1 / pl.invRangeSquared)
|
|
758
|
+
: 1000;
|
|
759
|
+
hdrpLights.push({ position: pl.position, range });
|
|
760
|
+
}
|
|
761
|
+
for (const sl of effectiveSpotLights) {
|
|
762
|
+
const range =
|
|
763
|
+
Number.isFinite(sl.invRangeSquared) && sl.invRangeSquared > 0
|
|
764
|
+
? Math.sqrt(1 / sl.invRangeSquared)
|
|
765
|
+
: 1000;
|
|
766
|
+
hdrpLights.push({ position: sl.position, range });
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
const clusterGrid =
|
|
770
|
+
frameState.installedPipelineConfig?.clusterGrid ?? DEFAULT_CLUSTER_GRID;
|
|
771
|
+
const gridX = clusterGrid.x;
|
|
772
|
+
const gridY = clusterGrid.y;
|
|
773
|
+
const gridZ = clusterGrid.z;
|
|
774
|
+
const clusterCount = gridX * gridY * gridZ;
|
|
775
|
+
|
|
776
|
+
const projMatrix = computeProjectionMatrix(camera);
|
|
777
|
+
const viewMatrix = computeViewMatrix(camera);
|
|
778
|
+
|
|
779
|
+
const clusterGridBuf =
|
|
780
|
+
frameState.hdrpClusterGridScratch === null ||
|
|
781
|
+
frameState.hdrpClusterGridScratch.length < clusterCount * 2
|
|
782
|
+
? new Uint32Array(clusterCount * 2)
|
|
783
|
+
: frameState.hdrpClusterGridScratch;
|
|
784
|
+
frameState.hdrpClusterGridScratch = clusterGridBuf;
|
|
785
|
+
const lightIndexListBuf =
|
|
786
|
+
frameState.hdrpLightIndexListScratch === null ||
|
|
787
|
+
frameState.hdrpLightIndexListScratch.length < LIGHT_INDEX_LIST_CAPACITY
|
|
788
|
+
? new Uint32Array(LIGHT_INDEX_LIST_CAPACITY)
|
|
789
|
+
: frameState.hdrpLightIndexListScratch;
|
|
790
|
+
frameState.hdrpLightIndexListScratch = lightIndexListBuf;
|
|
791
|
+
|
|
792
|
+
return {
|
|
793
|
+
hdrpLights,
|
|
794
|
+
clusterGrid,
|
|
795
|
+
gridX,
|
|
796
|
+
gridY,
|
|
797
|
+
gridZ,
|
|
798
|
+
clusterGridBuf,
|
|
799
|
+
lightIndexListBuf,
|
|
800
|
+
projMatrix,
|
|
801
|
+
viewMatrix,
|
|
802
|
+
};
|
|
803
|
+
},
|
|
804
|
+
);
|
|
805
|
+
|
|
806
|
+
const binResult = runHdrpClusterProfilePhase(
|
|
807
|
+
profilePhase,
|
|
808
|
+
'record/scene-state/hdrp-cluster/binner/bin-core',
|
|
809
|
+
() =>
|
|
810
|
+
bin(
|
|
811
|
+
hdrpLights,
|
|
812
|
+
viewMatrix,
|
|
813
|
+
projMatrix,
|
|
814
|
+
{ x: gridX, y: gridY, z: gridZ },
|
|
815
|
+
camera.near,
|
|
816
|
+
camera.far,
|
|
817
|
+
clusterGridBuf,
|
|
818
|
+
lightIndexListBuf,
|
|
819
|
+
LIGHT_INDEX_LIST_CAPACITY,
|
|
820
|
+
frameState.hdrpClusterBinScratch,
|
|
821
|
+
binnerProfile,
|
|
822
|
+
{ writeMembership: !gpuMembership },
|
|
823
|
+
),
|
|
824
|
+
);
|
|
825
|
+
|
|
826
|
+
if (!binResult.ok && !frameState.hdrpOncePerFrameFired.has('hdrp-index-list-overflow')) {
|
|
827
|
+
frameState.hdrpOncePerFrameFired.add('hdrp-index-list-overflow');
|
|
828
|
+
const detail = binResult.error.detail;
|
|
829
|
+
internals.errorRegistry.fire(
|
|
830
|
+
new HdrpIndexListOverflowError(detail.actual, detail.capacity),
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// Falsify injection point: FORGEAX_HDRP_FALSIFY_CLUSTER_GRID_ZERO
|
|
835
|
+
// zeroes the cluster_grid buffer so every fragment culls every light.
|
|
836
|
+
// Used by hello-hdrp-lighting smoke FALSIFY=cluster-grid-zero to
|
|
837
|
+
// prove the smoke has discriminability (must FAIL vs baseline).
|
|
838
|
+
// Read process via globalThis to keep this file @types/node-free.
|
|
839
|
+
const envFalsify = (globalThis as { process?: { env?: Record<string, string | undefined> } })
|
|
840
|
+
.process?.env;
|
|
841
|
+
if (envFalsify?.FORGEAX_HDRP_FALSIFY_CLUSTER_GRID_ZERO) {
|
|
842
|
+
clusterGridBuf.fill(0);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
return {
|
|
846
|
+
clusterGrid,
|
|
847
|
+
gridX,
|
|
848
|
+
gridY,
|
|
849
|
+
gridZ,
|
|
850
|
+
clusterGridBuf,
|
|
851
|
+
lightIndexListBuf,
|
|
852
|
+
lightIndexCount: binResult.ok ? binResult.value : 0,
|
|
853
|
+
};
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
const hdrpPayload = runHdrpClusterProfilePhase(
|
|
857
|
+
profilePhase,
|
|
858
|
+
'record/scene-state/hdrp-cluster/payload-packing',
|
|
859
|
+
() => {
|
|
860
|
+
const hdrpBuffers = getOrCreateHdrpBuffers(internals, clusterGrid);
|
|
861
|
+
if (hdrpBuffers === null) return null;
|
|
862
|
+
|
|
863
|
+
const lightCapacity = hdrpBuffers.storageBuffer ? 256 : HDRP_UNIFORM_LIGHT_CAPACITY;
|
|
864
|
+
const lightDataPayload = new Float32Array(lightCapacity * 16);
|
|
865
|
+
let slotIdx = 0;
|
|
866
|
+
for (const pl of effectivePointLights) {
|
|
867
|
+
if (slotIdx >= lightCapacity) break;
|
|
868
|
+
// feat-20260612-point-light-shadows-urp-hdrp M4 / T-M4-4
|
|
869
|
+
// (plan-strategy §D-8): thread the optional shadow info through
|
|
870
|
+
// packLightSlot. PointLightSnapshot.shadowAtlasLayer is set by
|
|
871
|
+
// extract's join pass when the entity carries PointLightShadow;
|
|
872
|
+
// sentinel -1 means no shadow (unshadowed evalPoint path).
|
|
873
|
+
const layer = pl.shadowAtlasLayer;
|
|
874
|
+
const packed =
|
|
875
|
+
layer !== undefined &&
|
|
876
|
+
layer >= 0 &&
|
|
877
|
+
pl.shadowNear !== undefined &&
|
|
878
|
+
pl.shadowFar !== undefined
|
|
879
|
+
? packLightSlot(pl, {
|
|
880
|
+
shadowAtlasLayer: layer,
|
|
881
|
+
near: pl.shadowNear,
|
|
882
|
+
far: pl.shadowFar,
|
|
883
|
+
})
|
|
884
|
+
: packLightSlot(pl);
|
|
885
|
+
lightDataPayload.set(packed, slotIdx * 16);
|
|
886
|
+
slotIdx += 1;
|
|
887
|
+
}
|
|
888
|
+
for (const sl of effectiveSpotLights) {
|
|
889
|
+
if (slotIdx >= lightCapacity) break;
|
|
890
|
+
const packed = packLightSlot(sl);
|
|
891
|
+
lightDataPayload.set(packed, slotIdx * 16);
|
|
892
|
+
slotIdx += 1;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// scope-amend-webgl2-ubo: SSAO intensity is folded into the
|
|
896
|
+
// cluster_uniform .w lane (formerly pad), removing the dedicated
|
|
897
|
+
// @binding(9) UBO that pushed fragment-stage UBO count past
|
|
898
|
+
// WebGL2's max_uniform_buffers_per_shader_stage=11. Disabled-SSAO
|
|
899
|
+
// path writes 0 so `mix(1.0, ssao*ao, 0.0) = 1.0` in the lighting
|
|
900
|
+
// shader (no PSO recompile across enable/disable).
|
|
901
|
+
const clusterSsaoConfig = frameState.installedPipelineConfig?.ssao;
|
|
902
|
+
const clusterSsaoIntensity =
|
|
903
|
+
clusterSsaoConfig !== undefined && clusterSsaoConfig.enabled === true
|
|
904
|
+
? (clusterSsaoConfig.intensity ?? 1.0)
|
|
905
|
+
: 0;
|
|
906
|
+
const clusterUniformPayload = packClusterUniform(
|
|
907
|
+
{ x: gridX, y: gridY, z: gridZ },
|
|
908
|
+
camera.near,
|
|
909
|
+
camera.far,
|
|
910
|
+
clusterSsaoIntensity,
|
|
911
|
+
Math.min(effectivePointLights.length + effectiveSpotLights.length, lightCapacity),
|
|
912
|
+
lightCapacity,
|
|
913
|
+
);
|
|
914
|
+
|
|
915
|
+
return {
|
|
916
|
+
hdrpBuffers,
|
|
917
|
+
lightDataUploadPayload: lightDataPayload.subarray(0, slotIdx * 16),
|
|
918
|
+
clusterUniformPayload: new Uint8Array(clusterUniformPayload),
|
|
919
|
+
};
|
|
920
|
+
},
|
|
921
|
+
);
|
|
922
|
+
|
|
923
|
+
runHdrpClusterProfilePhase(profilePhase, 'record/scene-state/hdrp-cluster/buffer-upload', () => {
|
|
924
|
+
if (hdrpPayload !== null) {
|
|
925
|
+
const { hdrpBuffers, lightDataUploadPayload, clusterUniformPayload } = hdrpPayload;
|
|
926
|
+
const lightDataUpload = internals.device.queue.writeBuffer(
|
|
927
|
+
hdrpBuffers.lightDataBuffer,
|
|
928
|
+
0,
|
|
929
|
+
lightDataUploadPayload,
|
|
930
|
+
);
|
|
931
|
+
if (!lightDataUpload.ok) internals.errorRegistry.fire(lightDataUpload.error);
|
|
932
|
+
|
|
933
|
+
if (hdrpBuffers.storageBuffer) {
|
|
934
|
+
if (gpuMembership) {
|
|
935
|
+
const lightBoundsUpload = internals.device.queue.writeBuffer(
|
|
936
|
+
hdrpBuffers.lightBoundsBuffer,
|
|
937
|
+
0,
|
|
938
|
+
frameState.hdrpClusterBinScratch.lightBounds.subarray(0, effectiveLightCount * 6),
|
|
939
|
+
);
|
|
940
|
+
if (!lightBoundsUpload.ok) internals.errorRegistry.fire(lightBoundsUpload.error);
|
|
941
|
+
}
|
|
942
|
+
const clusterGridUpload = internals.device.queue.writeBuffer(
|
|
943
|
+
hdrpBuffers.clusterGridBuffer,
|
|
944
|
+
0,
|
|
945
|
+
clusterGridBuf.subarray(0, gridX * gridY * gridZ * 2),
|
|
946
|
+
);
|
|
947
|
+
if (!clusterGridUpload.ok) internals.errorRegistry.fire(clusterGridUpload.error);
|
|
948
|
+
|
|
949
|
+
if (!gpuMembership && lightIndexCount > 0) {
|
|
950
|
+
const lightIndexListUpload = internals.device.queue.writeBuffer(
|
|
951
|
+
hdrpBuffers.lightIndexListBuffer,
|
|
952
|
+
0,
|
|
953
|
+
lightIndexListBuf.subarray(0, lightIndexCount),
|
|
954
|
+
);
|
|
955
|
+
if (!lightIndexListUpload.ok) internals.errorRegistry.fire(lightIndexListUpload.error);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
const clusterUniformUpload = internals.device.queue.writeBuffer(
|
|
960
|
+
hdrpBuffers.clusterUniformBuffer,
|
|
961
|
+
0,
|
|
962
|
+
clusterUniformPayload,
|
|
963
|
+
);
|
|
964
|
+
if (!clusterUniformUpload.ok) internals.errorRegistry.fire(clusterUniformUpload.error);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// ── feat-20260612-hdrp-ssao M1 / w6 + M7 / w33 ───────────────
|
|
968
|
+
// Per-frame SSAO uniform write (plan-strategy D-1 + D-C):
|
|
969
|
+
// view + projection + inverseProjection at offsets 0/64/128 +
|
|
970
|
+
// intensityPad (vec4 — x=intensity, y=radius, z=bias) at offset 192;
|
|
971
|
+
// total 256 B (matches host SSAO_UNIFORM_BYTES + WGSL struct).
|
|
972
|
+
// Single writeBuffer covers all four fields so one queue entry
|
|
973
|
+
// updates the entire UBO.
|
|
974
|
+
// Separate from View UBO (592 B invariant); does not affect
|
|
975
|
+
// material PSO bytecode.
|
|
976
|
+
//
|
|
977
|
+
// Writes when HDRP is active; config.ssao?.enabled guard comes in
|
|
978
|
+
// M4 / w19 after the config.ssao type narrowing is added.
|
|
979
|
+
{
|
|
980
|
+
const ssaoBufs = getOrCreateSsaoBuffers(internals);
|
|
981
|
+
if (ssaoBufs !== null) {
|
|
982
|
+
const sProj = computeProjectionMatrix(camera);
|
|
983
|
+
const sView = computeViewMatrix(camera);
|
|
984
|
+
// inverseProjection = inverse(projection): NDC -> view-space.
|
|
985
|
+
const invProjOnly = mat4.create();
|
|
986
|
+
mat4.invert(invProjOnly, sProj);
|
|
987
|
+
|
|
988
|
+
// Float32Array of 64 (256 B): 3 mat4 (48) + intensityPad vec4 (4)
|
|
989
|
+
// + 12 trailing padding floats. We only fill the declared region.
|
|
990
|
+
const ssaoUniformPayload = new Float32Array(64);
|
|
991
|
+
ssaoUniformPayload.set(sView, 0);
|
|
992
|
+
ssaoUniformPayload.set(sProj, 16);
|
|
993
|
+
ssaoUniformPayload.set(invProjOnly, 32);
|
|
994
|
+
// intensityPad carries the same resolved values as the graph SSAO
|
|
995
|
+
// calc pass; this early write keeps the shared UBO valid before the
|
|
996
|
+
// typed fullscreen pass executes.
|
|
997
|
+
const ssaoConfig = frameState.installedPipelineConfig?.ssao;
|
|
998
|
+
const parameters = getSsaoParameters(
|
|
999
|
+
ssaoConfig !== undefined && ssaoConfig.enabled === true ? ssaoConfig : undefined,
|
|
1000
|
+
);
|
|
1001
|
+
ssaoUniformPayload[48] = parameters.intensity;
|
|
1002
|
+
ssaoUniformPayload[49] = parameters.radius;
|
|
1003
|
+
ssaoUniformPayload[50] = parameters.bias;
|
|
1004
|
+
|
|
1005
|
+
const ssaoUniformRes = internals.device.queue.writeBuffer(
|
|
1006
|
+
ssaoBufs.uniformBuffer,
|
|
1007
|
+
0,
|
|
1008
|
+
ssaoUniformPayload,
|
|
1009
|
+
);
|
|
1010
|
+
if (!ssaoUniformRes.ok) internals.errorRegistry.fire(ssaoUniformRes.error);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* feat-20260704 M3/w18: resolve `tonemapActive` + `skyboxActive` for this
|
|
1018
|
+
* frame, extracted verbatim from `recordFrame`.
|
|
1019
|
+
*
|
|
1020
|
+
* feat-20260519-tonemap-reinhard-mvp: tonemap is active when the camera carries
|
|
1021
|
+
* `tonemap !== 'none'` (routes geometry into the HDR offscreen target + a
|
|
1022
|
+
* fullscreen tonemap pass). feat-20260531-skybox-env-background M2 / w9: skybox
|
|
1023
|
+
* is active only when a SkyboxBackground entity is present AND tonemap is active
|
|
1024
|
+
* (hdrColor is only allocated on the tonemap path). M3 / w20: once-warn when
|
|
1025
|
+
* tonemap is 'none' but a skybox exists (config issue, not resource-timing —
|
|
1026
|
+
* no structured error). M3 / w18: skybox degrades to clear-colour for a frame
|
|
1027
|
+
* while its cubemap view is not yet resident (lazy equirect projection pending
|
|
1028
|
+
* / failed; the lazy trigger owns the fire-once-on-failed error).
|
|
1029
|
+
*
|
|
1030
|
+
* @internal
|
|
1031
|
+
*/
|
|
1032
|
+
export function resolveSkyboxActive(
|
|
1033
|
+
internals: RenderSystemInternals,
|
|
1034
|
+
frameState: RenderFrameState,
|
|
1035
|
+
camera: CameraSnapshot,
|
|
1036
|
+
skybox: SkyboxSnapshot | undefined,
|
|
1037
|
+
): { tonemapActive: boolean; skyboxActive: boolean } {
|
|
1038
|
+
const tonemapActive = camera.tonemap !== 'none';
|
|
1039
|
+
let skyboxActive = skybox !== undefined && tonemapActive;
|
|
1040
|
+
// feat-20260531-skybox-env-background M3 / w20: once-warn when camera
|
|
1041
|
+
// tonemap is 'none' but a SkyboxBackground entity exists. The skybox
|
|
1042
|
+
// pass requires the HDR render target allocated by the tonemap path;
|
|
1043
|
+
// without it the skybox is skipped for this frame. This is a config
|
|
1044
|
+
// issue, not a resource-timing issue -- don't fire a structured error
|
|
1045
|
+
// (plan-strategy D-2 NOTE, charter P3 non-silent).
|
|
1046
|
+
if (skybox !== undefined && !tonemapActive && !frameState.warnedSkyboxTonemapNone) {
|
|
1047
|
+
frameState.warnedSkyboxTonemapNone = true;
|
|
1048
|
+
console.warn(
|
|
1049
|
+
'[forgeax] SkyboxBackground: skybox requires tonemap active (camera.tonemap !== "none") to write HDR target. The skybox pass will be skipped for this frame.',
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
// feat-20260531-skybox-env-background M3 / w18: degradation when cubemap
|
|
1053
|
+
// GPU view is not ready. getCubemapGpuView returns undefined if the
|
|
1054
|
+
// equirect-to-cube upload has not completed yet.
|
|
1055
|
+
if (skybox !== undefined && tonemapActive) {
|
|
1056
|
+
const cubemapView = internals.gpuStore.getCubemapGpuView(
|
|
1057
|
+
toShared<'EquirectAsset'>(skybox.equirectHandle),
|
|
1058
|
+
);
|
|
1059
|
+
if (cubemapView === undefined) {
|
|
1060
|
+
// The skybox reuses the Skylight's equirect handle; the cubemap
|
|
1061
|
+
// projection is driven lazily by the single trigger in `driveLazy
|
|
1062
|
+
// EquirectProjection` above (it owns the fire-and-forget launch AND the
|
|
1063
|
+
// fire-once-on-failed structured error). While the projection is
|
|
1064
|
+
// pending or has failed the cube view is not resident, so the skybox
|
|
1065
|
+
// pass degrades to the clear-colour background for this frame
|
|
1066
|
+
// (charter P3: it activates once the shared projection flips to
|
|
1067
|
+
// 'ready'). No error is fired here -- 'pending' is a normal transition
|
|
1068
|
+
// (firing per frame would flood the channel), and 'failed' is reported
|
|
1069
|
+
// once by the lazy trigger. (feat-20260630 M3 / w18.)
|
|
1070
|
+
skyboxActive = false;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
return { tonemapActive, skyboxActive };
|
|
1074
|
+
}
|