@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,1137 @@
|
|
|
1
|
+
// pbr-pipeline.ts -- PBR / unlit pipeline-layout factories (M4 round-4 D-5).
|
|
2
|
+
//
|
|
3
|
+
// Anchors:
|
|
4
|
+
// - plan-strategy D-5 (round-4 REVISED): the PBR pipeline keeps a 4-slot
|
|
5
|
+
// pipeline layout `[view, material, mesh-array, instances]`. The
|
|
6
|
+
// material BGL grows from the derived user region by appending the 7
|
|
7
|
+
// Skylight resources via `mergeSkylightIntoMaterialBgl`. The
|
|
8
|
+
// unlit pipeline keeps its 7-entry material BGL (no Skylight binding
|
|
9
|
+
// 7..13 contamination) so unlit demos don't carry IBL state.
|
|
10
|
+
// - charter P4: same pipeline layout shape drives Skylight present +
|
|
11
|
+
// absent paths -- AI users do not branch on Skylight existence.
|
|
12
|
+
// - feat-20260520-skylight-ibl-cubemap M4 / t59 (round-4): the
|
|
13
|
+
// pipeline-layout construction migrates out of `createRenderer.ts`
|
|
14
|
+
// into this dedicated module so M4 round-4 tests can mock the device
|
|
15
|
+
// and inspect the captured descriptors without standing up the full
|
|
16
|
+
// createRenderer + asset registry + manifest stack.
|
|
17
|
+
//
|
|
18
|
+
// The factory functions return both the captured handles AND the
|
|
19
|
+
// `bindGroupLayouts` array passed to `device.createPipelineLayout`. Callers
|
|
20
|
+
// (the createRenderer step that wires the standard + standard-HDR
|
|
21
|
+
// `RenderPipeline` instances) consume the result by name; tests inspect
|
|
22
|
+
// `device.createBindGroupLayout.mock.calls` to verify shape (t57).
|
|
23
|
+
|
|
24
|
+
import type {
|
|
25
|
+
BindGroup,
|
|
26
|
+
BindGroupEntry,
|
|
27
|
+
BindGroupLayout,
|
|
28
|
+
BindGroupLayoutDescriptor,
|
|
29
|
+
Buffer,
|
|
30
|
+
PipelineLayout,
|
|
31
|
+
RhiDevice,
|
|
32
|
+
Sampler,
|
|
33
|
+
TextureView,
|
|
34
|
+
} from '@forgeax/engine-rhi';
|
|
35
|
+
import { DEFAULT_STANDARD_PBR_PARAM_SCHEMA, type ShaderCatalog } from '@forgeax/engine-shader';
|
|
36
|
+
import { derive, type ParamSchemaEntry } from '@forgeax/engine-types';
|
|
37
|
+
import { GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX } from './gpu-stage';
|
|
38
|
+
import type { PipelineSpec } from './pipeline-spec-types';
|
|
39
|
+
|
|
40
|
+
// Stub PipelineSpec used by the BGL-only call sites. The dispatcher only reads
|
|
41
|
+
// `spec.shader` when a registry is supplied for reflection; for caps-driven
|
|
42
|
+
// kinds (pbr-view / pbr-mesh-array / pbr-instances / pbr-skin-mesh-array) and
|
|
43
|
+
// for the no-registry material path the spec content is unused. A single
|
|
44
|
+
// frozen stub keeps the call sites readable and is allocation-free.
|
|
45
|
+
//
|
|
46
|
+
// D-13 round-2 dispatcher landing — see plan-decisions D-13.
|
|
47
|
+
const BGL_ONLY_SPEC_STUB: PipelineSpec = Object.freeze({
|
|
48
|
+
shader: { id: '', passKind: 'forward', variantSet: undefined },
|
|
49
|
+
attachments: { colorFormats: [], depthFormat: undefined, sampleCount: 1 },
|
|
50
|
+
geometry: { topology: 'triangle-list', vertexLayout: {} },
|
|
51
|
+
renderState: undefined,
|
|
52
|
+
}) as PipelineSpec;
|
|
53
|
+
|
|
54
|
+
// ─── Device owner ───────────────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
/** The PBR layout builder consumes only the two creation methods it owns. */
|
|
57
|
+
export type PbrPipelineDevice = Pick<RhiDevice, 'createBindGroupLayout' | 'createPipelineLayout'>;
|
|
58
|
+
|
|
59
|
+
// ─── Result shape ───────────────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
export interface PbrPipelineLayoutBundle {
|
|
62
|
+
/** Pipeline layout passed to `createRenderPipeline({ layout })`. */
|
|
63
|
+
readonly pipelineLayout: PipelineLayout;
|
|
64
|
+
/** view BindGroupLayout (slot 0). */
|
|
65
|
+
readonly viewBgl: BindGroupLayout;
|
|
66
|
+
/**
|
|
67
|
+
* PBR material BindGroupLayout (slot 1) -- derived user-region entries plus
|
|
68
|
+
* Skylight and lightmap injection.
|
|
69
|
+
*/
|
|
70
|
+
readonly materialBgl: BindGroupLayout;
|
|
71
|
+
/** Per-entity mesh BindGroupLayout (slot 2). */
|
|
72
|
+
readonly meshArrayBgl: BindGroupLayout;
|
|
73
|
+
/** Per-instance storage BindGroupLayout (slot 3). */
|
|
74
|
+
readonly instancesBgl: BindGroupLayout;
|
|
75
|
+
/**
|
|
76
|
+
* Same 4 layouts in slot order. Useful for assertion sites that check the
|
|
77
|
+
* pipeline-layout `bindGroupLayouts` array shape (t57 (a) + (d)).
|
|
78
|
+
*/
|
|
79
|
+
readonly bindGroupLayouts: readonly [
|
|
80
|
+
BindGroupLayout,
|
|
81
|
+
BindGroupLayout,
|
|
82
|
+
BindGroupLayout,
|
|
83
|
+
BindGroupLayout,
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ─── Base entries (round-4 SSOT) ────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The built-in standard-PBR material paramSchema's texture/user-region shape,
|
|
91
|
+
* used as the fallback when the material BGL is built without a registry
|
|
92
|
+
* (the caps-driven `buildPbrPipelineLayouts` seam). Declares the 3 standard
|
|
93
|
+
* user-region textures + a numeric UBO run; `derive()` collapses the numerics
|
|
94
|
+
* into binding 0 and emits sampler/texture pairs at 1..6 — byte-equivalent to
|
|
95
|
+
* the legacy fixed base-7. The shared PBR parameter contract comes from the
|
|
96
|
+
* shader package; this module only derives the GPU layout.
|
|
97
|
+
*/
|
|
98
|
+
/**
|
|
99
|
+
* Build the PBR material BGL **user-region** from a paramSchema via the
|
|
100
|
+
* `derive()` SSOT (D-1). The user-region is binding 0 (the run-merged material
|
|
101
|
+
* UBO) followed by one sampler/texture pair per declared texture. Engine
|
|
102
|
+
* injection (IBL + lightmap) is appended AFTER this region by the caller via
|
|
103
|
+
* `appendInjection`, with start binding = `userRegion.length` — so a 4-texture
|
|
104
|
+
* custom schema (e.g. parallax + heightTexture) shifts the injection region by
|
|
105
|
+
* one sampler/texture pair automatically.
|
|
106
|
+
*
|
|
107
|
+
* The built-in `default-standard-pbr` paramSchema declares exactly 4 textures,
|
|
108
|
+
* so this derives to binding 0 UBO + 4 pairs = 9 entries. Injection is appended
|
|
109
|
+
* after that derived region.
|
|
110
|
+
*
|
|
111
|
+
* One material-UBO convention is layered on top of the pure `derive()` output:
|
|
112
|
+
* binding 0 is patched to `{ type: 'uniform', hasDynamicOffset: true }` with
|
|
113
|
+
* `VERTEX | FRAGMENT` visibility. The material UBO is bound with a per-submesh
|
|
114
|
+
* dynamic offset (`render-system-record.ts setBindGroup(1, bg, [offset])`) and
|
|
115
|
+
* the vertex stage reads material params, so this is required for GPU
|
|
116
|
+
* validation. `derive()` stays FRAGMENT-only / no-dynamic-offset for its other
|
|
117
|
+
* consumers (it is the generic SSOT, not the material-UBO authority).
|
|
118
|
+
*
|
|
119
|
+
* @param paramSchema - the material shader's paramSchema (defaults to the
|
|
120
|
+
* built-in standard-PBR shape when omitted, for the caps-driven seam).
|
|
121
|
+
*/
|
|
122
|
+
export function buildPbrMaterialUserRegionEntries(
|
|
123
|
+
paramSchema: readonly ParamSchemaEntry[] = DEFAULT_STANDARD_PBR_PARAM_SCHEMA,
|
|
124
|
+
): GPUBindGroupLayoutEntry[] {
|
|
125
|
+
const derived = derive(paramSchema);
|
|
126
|
+
// Project the engine-owned entry shape into the DOM WebGPU descriptor. Omit
|
|
127
|
+
// absent optional members so exactOptionalPropertyTypes remains true at the
|
|
128
|
+
// boundary instead of leaking an `undefined` property into the descriptor.
|
|
129
|
+
const entries = derived.bglEntries.map(
|
|
130
|
+
(entry): GPUBindGroupLayoutEntry => ({
|
|
131
|
+
binding: entry.binding,
|
|
132
|
+
visibility: entry.visibility,
|
|
133
|
+
...(entry.buffer === undefined ? {} : { buffer: entry.buffer }),
|
|
134
|
+
...(entry.sampler === undefined ? {} : { sampler: entry.sampler }),
|
|
135
|
+
...(entry.texture === undefined ? {} : { texture: entry.texture }),
|
|
136
|
+
...(entry.storageTexture === undefined ? {} : { storageTexture: entry.storageTexture }),
|
|
137
|
+
}),
|
|
138
|
+
);
|
|
139
|
+
// Patch binding 0 (the material UBO) to the dynamic-offset, vertex-visible
|
|
140
|
+
// material-UBO contract. derive() emits binding 0 as the first numeric run's
|
|
141
|
+
// merged UBO; an empty schema has no binding-0 UBO and needs no patch.
|
|
142
|
+
const ubo = entries[0];
|
|
143
|
+
if (ubo !== undefined && ubo.binding === 0 && ubo.buffer !== undefined) {
|
|
144
|
+
entries[0] = {
|
|
145
|
+
binding: 0,
|
|
146
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
147
|
+
buffer: { type: 'uniform', hasDynamicOffset: true },
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return entries;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ─── appendInjection — generic engine-injection BGL appender (M3 / w15) ──────
|
|
154
|
+
//
|
|
155
|
+
// Decision anchors (plan-strategy §2):
|
|
156
|
+
// - D-6 appendInjection(bgl, kind) replaces the previous hardcoded
|
|
157
|
+
// emissive/AO start-binding literal (=14). The starting binding
|
|
158
|
+
// number is computed from `bgl.length`, byte-equivalent to
|
|
159
|
+
// `derive(schema).userRegionBindingEnd` when `bgl` is the BGL list
|
|
160
|
+
// derive returned for the user paramSchema.
|
|
161
|
+
// - R-1 the 14-slot user-region assumption breaks once D-3 merges UBO;
|
|
162
|
+
// appendInjection lets the material BGL grow / shrink without
|
|
163
|
+
// churning every injection site.
|
|
164
|
+
//
|
|
165
|
+
// Closed union of injection kinds (plan-strategy §2 D-6):
|
|
166
|
+
// - 'shadow' reserved for future material-level shadow injection
|
|
167
|
+
// (sampler_comparison + texture_depth_2d, 2 entries).
|
|
168
|
+
// The active shadow bindings live in the view BGL today
|
|
169
|
+
// (group(0) bindings 3..7); this kind is the seam for
|
|
170
|
+
// each per-material shadow override surface a future feat
|
|
171
|
+
// wires onto group(1).
|
|
172
|
+
// - 'ibl' the 7 IBL / Skylight entries (irradiance / prefilter
|
|
173
|
+
// cube + brdfLut 2d + 3 samplers + intensity uniform).
|
|
174
|
+
// Used by `buildPbrPipelineLayouts` after the user-region
|
|
175
|
+
// user paramSchema entries are emitted.
|
|
176
|
+
// - 'lightmap' the 4 emissive + occlusion entries (sampler + texture
|
|
177
|
+
// pair x 2). The historical name is "emissive/AO"; we
|
|
178
|
+
// keep that meaning under the generic 'lightmap' label
|
|
179
|
+
// (per-surface secondary-lighting injection) so future
|
|
180
|
+
// lightmap support lands without renaming the kind.
|
|
181
|
+
export type InjectionKind = keyof typeof INJECTION_KIND_LENGTHS;
|
|
182
|
+
|
|
183
|
+
const IBL_INJECTION_LENGTH = 7;
|
|
184
|
+
const LIGHTMAP_INJECTION_LENGTH = 4;
|
|
185
|
+
const SHADOW_INJECTION_LENGTH = 2;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Append the engine-injection BGL entries for the given `kind` after the
|
|
189
|
+
* user-region BGL entries, with binding numbers starting at `bgl.length`.
|
|
190
|
+
*
|
|
191
|
+
* The function reads `bgl.length` (NOT a hardcoded constant) so each
|
|
192
|
+
* user-region size — derived from `derive(schema).userRegionBindingEnd` or
|
|
193
|
+
* computed manually — flows through to the injection start binding without
|
|
194
|
+
* a coupled edit.
|
|
195
|
+
*
|
|
196
|
+
* Returns ONLY the injected entries; the caller spreads them after `bgl`:
|
|
197
|
+
*
|
|
198
|
+
* ```ts
|
|
199
|
+
* const merged = [...userBgl, ...appendInjection(userBgl, 'ibl')];
|
|
200
|
+
* device.createBindGroupLayout({ entries: merged });
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
export function appendInjection(
|
|
204
|
+
bgl: readonly GPUBindGroupLayoutEntry[],
|
|
205
|
+
kind: InjectionKind,
|
|
206
|
+
): GPUBindGroupLayoutEntry[] {
|
|
207
|
+
const start = bgl.length;
|
|
208
|
+
switch (kind) {
|
|
209
|
+
case 'ibl':
|
|
210
|
+
return [
|
|
211
|
+
// binding start+0: irradianceMap (texture_cube)
|
|
212
|
+
{
|
|
213
|
+
binding: start,
|
|
214
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
215
|
+
texture: { sampleType: 'float', viewDimension: 'cube' },
|
|
216
|
+
},
|
|
217
|
+
// binding start+1: irradianceSampler
|
|
218
|
+
{
|
|
219
|
+
binding: start + 1,
|
|
220
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
221
|
+
sampler: { type: 'filtering' },
|
|
222
|
+
},
|
|
223
|
+
// binding start+2: prefilterMap (texture_cube)
|
|
224
|
+
{
|
|
225
|
+
binding: start + 2,
|
|
226
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
227
|
+
texture: { sampleType: 'float', viewDimension: 'cube' },
|
|
228
|
+
},
|
|
229
|
+
// binding start+3: prefilterSampler
|
|
230
|
+
{
|
|
231
|
+
binding: start + 3,
|
|
232
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
233
|
+
sampler: { type: 'filtering' },
|
|
234
|
+
},
|
|
235
|
+
// binding start+4: brdfLut (texture_2d)
|
|
236
|
+
{
|
|
237
|
+
binding: start + 4,
|
|
238
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
239
|
+
texture: { sampleType: 'float', viewDimension: '2d' },
|
|
240
|
+
},
|
|
241
|
+
// binding start+5: brdfLutSampler
|
|
242
|
+
{
|
|
243
|
+
binding: start + 5,
|
|
244
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
245
|
+
sampler: { type: 'filtering' },
|
|
246
|
+
},
|
|
247
|
+
// binding start+6: uniform { intensity: f32 }
|
|
248
|
+
{
|
|
249
|
+
binding: start + 6,
|
|
250
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
251
|
+
buffer: { type: 'uniform' },
|
|
252
|
+
},
|
|
253
|
+
];
|
|
254
|
+
case 'lightmap':
|
|
255
|
+
return [
|
|
256
|
+
// emissive sampler + texture pair
|
|
257
|
+
{
|
|
258
|
+
binding: start,
|
|
259
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
260
|
+
sampler: { type: 'filtering' },
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
binding: start + 1,
|
|
264
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
265
|
+
texture: { sampleType: 'float', viewDimension: '2d' },
|
|
266
|
+
},
|
|
267
|
+
// occlusion sampler + texture pair
|
|
268
|
+
{
|
|
269
|
+
binding: start + 2,
|
|
270
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
271
|
+
sampler: { type: 'filtering' },
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
binding: start + 3,
|
|
275
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
276
|
+
texture: { sampleType: 'float', viewDimension: '2d' },
|
|
277
|
+
},
|
|
278
|
+
];
|
|
279
|
+
case 'shadow':
|
|
280
|
+
return [
|
|
281
|
+
{
|
|
282
|
+
binding: start,
|
|
283
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
284
|
+
sampler: { type: 'comparison' },
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
binding: start + 1,
|
|
288
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
289
|
+
texture: { sampleType: 'depth', viewDimension: '2d' },
|
|
290
|
+
},
|
|
291
|
+
];
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Closed-set length sentinels — the map is the membership owner.
|
|
296
|
+
export const INJECTION_KIND_LENGTHS = {
|
|
297
|
+
shadow: SHADOW_INJECTION_LENGTH,
|
|
298
|
+
ibl: IBL_INJECTION_LENGTH,
|
|
299
|
+
lightmap: LIGHTMAP_INJECTION_LENGTH,
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Caps shape consumed by the BGL factory functions for storage-buffer vs
|
|
304
|
+
* uniform-buffer branching. Mirrors the two fields the engine reads from
|
|
305
|
+
* `RhiCaps` (plan D-4 + D-5).
|
|
306
|
+
*/
|
|
307
|
+
export interface PbrCaps {
|
|
308
|
+
readonly storageBuffer: boolean;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* The view BGL entry list. binding 0 = view UBO (vertex + fragment);
|
|
313
|
+
* binding 1 = pointLights (storage or uniform, per caps);
|
|
314
|
+
* binding 2 = spotLights (storage or uniform, per caps);
|
|
315
|
+
* binding 3 = directional shadowMap atlas (texture_depth_2d, vertex+fragment).
|
|
316
|
+
* feat-20260613-csm-cascaded-shadow-maps: this is the CSM atlas — N
|
|
317
|
+
* cascades tiled into one 2D depth texture, sampled via per-cascade UV
|
|
318
|
+
* mapping in `lighting-directional.wgsl`. Single binding survives N=1..4
|
|
319
|
+
* (no array-layer form; cascades live in viewport offsets per the
|
|
320
|
+
* check-csm-unique-shadow-path grep gate).
|
|
321
|
+
* binding 4 = shadow comparison sampler (shared by directional + point);
|
|
322
|
+
* binding 5 = point shadow cube_array depth atlas (texture_depth_cube_array;
|
|
323
|
+
* fragment-only). feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1.
|
|
324
|
+
* binding 6 = point shadow params UBO (`array<vec4<f32>, 4>`, 64 B;
|
|
325
|
+
* fragment-only). One lane per shadow-casting point light slot
|
|
326
|
+
* (shadowAtlasLayer in [0, 4)) carrying `(near, far, 1/(far-near), 0)`.
|
|
327
|
+
* binding 7 = shadowCasterCascade UBO (16 B; vertex + fragment). Per-pass
|
|
328
|
+
* cascade-index uniform consumed exclusively by `shadow_caster.wgsl` to
|
|
329
|
+
* pick `view.lightViewProj_X` for the cascade currently being rasterized
|
|
330
|
+
* (feat-20260613-csm-cascaded-shadow-maps M5 / w28). Forward PBR shaders
|
|
331
|
+
* declare the binding via `common.wgsl` but do not reference it; WebGPU
|
|
332
|
+
* still requires a populated entry on every view BG so the host writes a
|
|
333
|
+
* stable singleton buffer.
|
|
334
|
+
* binding 8 = spot shadow atlas (texture_depth_2d; fragment-only).
|
|
335
|
+
* feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5). A single 2D depth
|
|
336
|
+
* texture holding up to 4 spot shadows in a 2x2 tile grid. ALWAYS-ON (no caps
|
|
337
|
+
* gate — `texture_depth_2d` is compat-safe everywhere), matching the
|
|
338
|
+
* unconditional `spotShadowMap` WGSL declaration in common.wgsl. Reuses the
|
|
339
|
+
* comparison sampler at binding 4 (no binding 9). Every view BG must populate
|
|
340
|
+
* binding 8 (real spotShadowDepth view when spot shadows run, else a 1x1
|
|
341
|
+
* fallback depth view cleared to fully-lit).
|
|
342
|
+
*
|
|
343
|
+
* Mirrors feat-20260519-light-casters M3 D-S1 layout +
|
|
344
|
+
* feat-20260520-directional-light-shadow-mapping M2 / w14 (D-1) shadow
|
|
345
|
+
* map binding +
|
|
346
|
+
* feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1 BGL hookup
|
|
347
|
+
* (always-on bindings 5/6 paired with the unconditional `POINT_SHADOW_AVAILABLE`
|
|
348
|
+
* define registered in vite-plugin-shader) +
|
|
349
|
+
* feat-20260613-csm-cascaded-shadow-maps M5 / w28 (binding 7 cascade UBO).
|
|
350
|
+
* binding 10 (Points/Lines viewport UBO; always bound for the shared view
|
|
351
|
+
* layout and consumed only by the dedicated points-lines shader).
|
|
352
|
+
* Isolated here so M4 round-4 tests can recreate the layout.
|
|
353
|
+
*
|
|
354
|
+
* feat-20260526-pbr-uniform-fallback-no-storage-buffer M3 / w9:
|
|
355
|
+
* caps.storageBuffer===false switches bindings 1+2 from
|
|
356
|
+
* 'read-only-storage' to 'uniform'.
|
|
357
|
+
*/
|
|
358
|
+
export function buildPbrViewBglEntries(caps: PbrCaps): GPUBindGroupLayoutEntry[] {
|
|
359
|
+
const lightBufType: GPUBufferBindingType = caps.storageBuffer ? 'read-only-storage' : 'uniform';
|
|
360
|
+
return [
|
|
361
|
+
{
|
|
362
|
+
binding: 0,
|
|
363
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
364
|
+
buffer: { type: 'uniform' },
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
binding: 1,
|
|
368
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
369
|
+
buffer: { type: lightBufType },
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
binding: 2,
|
|
373
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
374
|
+
buffer: { type: lightBufType },
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
binding: 3,
|
|
378
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
379
|
+
texture: { sampleType: 'depth', viewDimension: '2d' },
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
binding: 4,
|
|
383
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
384
|
+
sampler: { type: 'comparison' },
|
|
385
|
+
},
|
|
386
|
+
// feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: point shadow
|
|
387
|
+
// cube_array depth atlas. Bound to either the real ShadowAtlas
|
|
388
|
+
// cube_array view (when point shadows are active) or a 1x1x6 fallback
|
|
389
|
+
// cube_array view cleared to 1.0 (fully lit). Visibility is FRAGMENT
|
|
390
|
+
// only -- the directional binding 3 is VERTEX|FRAGMENT for shadow
|
|
391
|
+
// probe-debug sampling, but the cube atlas has no host-side probe path.
|
|
392
|
+
{
|
|
393
|
+
binding: 5,
|
|
394
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
395
|
+
texture: { sampleType: 'depth', viewDimension: 'cube-array' },
|
|
396
|
+
},
|
|
397
|
+
// feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: point shadow
|
|
398
|
+
// params UBO. Carries `array<vec4<f32>, 4>` = 64 B with one lane per
|
|
399
|
+
// shadow-casting point light slot (shadowAtlasLayer in [0, 4)). Each
|
|
400
|
+
// lane stores `(near, far, 1/(far-near), 0)` so the fragment-shader
|
|
401
|
+
// depth-ref reconstruction (lighting-punctual.wgsl evalPointShadowed)
|
|
402
|
+
// can avoid sampling LightSlot for the URP path. HDRP rides the same
|
|
403
|
+
// constants on `LightSlot.kind_and_pad.zw` so binding 6 is unused on
|
|
404
|
+
// HDRP shaders even though the BGL declares it (charter P4 single SSOT
|
|
405
|
+
// BGL across pipelines; the HDRP variant simply doesn't reference the
|
|
406
|
+
// binding in WGSL, which is allowed).
|
|
407
|
+
{
|
|
408
|
+
binding: 6,
|
|
409
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
410
|
+
buffer: { type: 'uniform' },
|
|
411
|
+
},
|
|
412
|
+
// feat-20260613-csm-cascaded-shadow-maps M5 / w28: shadowCasterCascade
|
|
413
|
+
// UBO (16 B). Carries the 0-based cascade index of the shadow pass
|
|
414
|
+
// currently being rasterized so `shadow_caster.wgsl` can index into
|
|
415
|
+
// `view.lightViewProj_X` per cascade. Shifted from binding 5 to
|
|
416
|
+
// binding 7 on 2026-06-13 to make room for point-shadow bindings 5/6
|
|
417
|
+
// (they predate this feat in main; CSM's slot was the optimal-yield
|
|
418
|
+
// give since point-shadow needs FRAGMENT-only and the cascade UBO
|
|
419
|
+
// needs vertex-stage too — keeping cascade higher avoids interleaving
|
|
420
|
+
// visibility flags within the contiguous shadow-binding cluster).
|
|
421
|
+
{
|
|
422
|
+
binding: 7,
|
|
423
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
424
|
+
buffer: { type: 'uniform' },
|
|
425
|
+
},
|
|
426
|
+
// feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5): spot shadow
|
|
427
|
+
// atlas. A single `texture_depth_2d` holding up to 4 spot shadows in a 2x2
|
|
428
|
+
// tile grid (urp-pipeline.ts spotShadowDepth). FRAGMENT-only — the spot
|
|
429
|
+
// shadow factor is reconstructed at fragment time via perspective-divide in
|
|
430
|
+
// `evalSpotShadowed` (lighting-punctual.wgsl).
|
|
431
|
+
//
|
|
432
|
+
// ALWAYS-ON (no caps gate, unlike the point cube_array atlas at binding 5
|
|
433
|
+
// which rides POINT_SHADOW_AVAILABLE): spot uses `texture_depth_2d` which is
|
|
434
|
+
// compat-safe in every WebGPU profile, so the binding is unconditionally
|
|
435
|
+
// declared. The matching WGSL declaration is `spotShadowMap` at @group(0)
|
|
436
|
+
// binding 8 in common.wgsl (also unconditional) — the two must stay in
|
|
437
|
+
// lock-step or WebGPU validation rejects the bind group at smoke time
|
|
438
|
+
// (memory: BGL shape mismatch is a browser-path-only bug). No binding 9
|
|
439
|
+
// sampler: spot reuses the comparison sampler at binding 4.
|
|
440
|
+
// feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5): spot shadow 2D
|
|
441
|
+
// atlas, the LAST view-BG binding. The per-spot fragment-read perspective
|
|
442
|
+
// lightViewProj matrices that w24 originally declared at a standalone
|
|
443
|
+
// binding 9 uniform buffer were folded into the View UBO (binding 0,
|
|
444
|
+
// `view.spotLightViewProj`) in w25 (scope-amend webkit-fallback): the
|
|
445
|
+
// standalone binding pushed the WebGL2 fallback fragment uniform-buffer
|
|
446
|
+
// count to 12, over GLES 3.0's `max_uniform_buffers_per_shader_stage = 11`,
|
|
447
|
+
// crashing pipeline-layout creation on the compat path (this feat's target).
|
|
448
|
+
{
|
|
449
|
+
binding: 8,
|
|
450
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
451
|
+
texture: { sampleType: 'depth', viewDimension: '2d' },
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
binding: 10,
|
|
455
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
456
|
+
buffer: { type: 'uniform', hasDynamicOffset: true },
|
|
457
|
+
},
|
|
458
|
+
];
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// ─── PBR pipeline layout factory ────────────────────────────────────────────
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Build the PBR pipeline layout under D-5 round-4: 4 slots `[view,
|
|
465
|
+
* material, mesh-array, instances]`; the material BGL is derived from the
|
|
466
|
+
* standard material schema and engine injection chain.
|
|
467
|
+
*
|
|
468
|
+
* `caps.storageBuffer===false` switches every storage-buffer BGL entry
|
|
469
|
+
* (view bindings 1+2, mesh-array, instances) to `uniform`.
|
|
470
|
+
*
|
|
471
|
+
* Throws on each `createBindGroupLayout` / `createPipelineLayout` Result
|
|
472
|
+
* failure -- the engine bootstrap path (createRenderer) wraps the call in
|
|
473
|
+
* `runShimSyncStep` to fold the throw into the structured error pipe.
|
|
474
|
+
*/
|
|
475
|
+
export function buildPbrPipelineLayouts(
|
|
476
|
+
device: PbrPipelineDevice,
|
|
477
|
+
caps: PbrCaps,
|
|
478
|
+
): PbrPipelineLayoutBundle {
|
|
479
|
+
// D-13 round-2: 4 BGLs route through buildBindGroupLayoutDescriptor.
|
|
480
|
+
// The dispatcher reads kind + caps; spec content is unused without a
|
|
481
|
+
// registry (no shader-axis reflection at this seam — the 4 BGLs are
|
|
482
|
+
// caps-driven literals + the deterministic Skylight + lightmap merge
|
|
483
|
+
// sequence that has no dependency on shader.id).
|
|
484
|
+
const viewBglRes = device.createBindGroupLayout(
|
|
485
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'pbr-view', caps }),
|
|
486
|
+
);
|
|
487
|
+
if (!viewBglRes.ok) throw viewBglRes.error;
|
|
488
|
+
|
|
489
|
+
// Material BGL: derived user region + Skylight + lightmap injection.
|
|
490
|
+
// feat-20260613 fix-issue-5: drop the buildPbrMaterialEmissiveAoEntries
|
|
491
|
+
// shim. The lightmap injection start binding is computed from the post-
|
|
492
|
+
// skylight BGL length (= 14) directly inside appendInjection.
|
|
493
|
+
const materialBglRes = device.createBindGroupLayout(
|
|
494
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'pbr-material-merged' }),
|
|
495
|
+
);
|
|
496
|
+
if (!materialBglRes.ok) throw materialBglRes.error;
|
|
497
|
+
|
|
498
|
+
// mesh-array BGL.
|
|
499
|
+
const meshArrayBglRes = device.createBindGroupLayout(
|
|
500
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'pbr-mesh-array', caps }),
|
|
501
|
+
);
|
|
502
|
+
if (!meshArrayBglRes.ok) throw meshArrayBglRes.error;
|
|
503
|
+
|
|
504
|
+
// instances BGL.
|
|
505
|
+
const instancesBglRes = device.createBindGroupLayout(
|
|
506
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'pbr-instances', caps }),
|
|
507
|
+
);
|
|
508
|
+
if (!instancesBglRes.ok) throw instancesBglRes.error;
|
|
509
|
+
|
|
510
|
+
// Pipeline layout (4 slots).
|
|
511
|
+
const layouts: readonly [BindGroupLayout, BindGroupLayout, BindGroupLayout, BindGroupLayout] = [
|
|
512
|
+
viewBglRes.value,
|
|
513
|
+
materialBglRes.value,
|
|
514
|
+
meshArrayBglRes.value,
|
|
515
|
+
instancesBglRes.value,
|
|
516
|
+
];
|
|
517
|
+
const pipelineLayoutRes = device.createPipelineLayout({
|
|
518
|
+
label: 'pbr-pl',
|
|
519
|
+
bindGroupLayouts: layouts,
|
|
520
|
+
});
|
|
521
|
+
if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
|
|
522
|
+
|
|
523
|
+
return {
|
|
524
|
+
pipelineLayout: pipelineLayoutRes.value,
|
|
525
|
+
viewBgl: viewBglRes.value,
|
|
526
|
+
materialBgl: materialBglRes.value,
|
|
527
|
+
meshArrayBgl: meshArrayBglRes.value,
|
|
528
|
+
instancesBgl: instancesBglRes.value,
|
|
529
|
+
bindGroupLayouts: layouts,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// ─── PBR skin material-shader identifier (SSOT) ────────────────────────────
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* SSOT for the skin material shader's registered identifier. The shader
|
|
537
|
+
* package registers under this string (see register-default-standard-pbr-skin.ts
|
|
538
|
+
* `RESERVED_ID`); runtime dispatch sites import this constant rather than
|
|
539
|
+
* carrying a literal so a future rename is a one-line change. AC-09 grep
|
|
540
|
+
* gate: the body of `selectPipelineLayoutForVariant` MUST NOT contain a
|
|
541
|
+
* literal `'forgeax::pbr-skin'` -- callers map this constant to
|
|
542
|
+
* `LayoutKind = 'pbr-skin'` upstream.
|
|
543
|
+
*/
|
|
544
|
+
export const SKIN_MATERIAL_SHADER_ID = 'forgeax::pbr-skin' as const;
|
|
545
|
+
|
|
546
|
+
/** Returns true for the engine-shipped standard-PBR material shader family. */
|
|
547
|
+
export function isStandardPbrMaterialShader(shaderId: string | undefined): boolean {
|
|
548
|
+
return (
|
|
549
|
+
shaderId === 'forgeax::default-standard-pbr' ||
|
|
550
|
+
shaderId === SKIN_MATERIAL_SHADER_ID ||
|
|
551
|
+
shaderId === 'forgeax::default-standard-pbr-skin'
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// ─── PBR skin pipeline layout factory (bug-20260611) ───────────────────────
|
|
556
|
+
//
|
|
557
|
+
// The skin material shader (`forgeax::pbr-skin`, registered by
|
|
558
|
+
// `register-default-standard-pbr-skin.ts`) needs the same 4-slot layout shape
|
|
559
|
+
// as standard PBR EXCEPT for slot 2: its mesh-array BGL declares **2**
|
|
560
|
+
// dynamic-offset entries (binding 0 = meshes, binding 1 = palette) versus
|
|
561
|
+
// standard PBR's single binding 0. Without a dedicated pipeline layout the
|
|
562
|
+
// skin shader's `@group(2) @binding(1) palette : array<mat4x4<f32>>` reference
|
|
563
|
+
// trips a `Binding doesn't exist in [BindGroupLayoutInternal "pbr-mesh-array-bgl"]`
|
|
564
|
+
// validation error in `device.createRenderPipeline`, surfaced as
|
|
565
|
+
// `RhiError limit-exceeded` and an invalid command buffer (Playwright TDD trace
|
|
566
|
+
// captured 2026-06-11 in apps/hello/skin).
|
|
567
|
+
//
|
|
568
|
+
// The factory **reuses** view / material / instances BGL handles produced by
|
|
569
|
+
// `buildPbrPipelineLayouts` (charter P4: a single SSOT BGL for each slot the
|
|
570
|
+
// shapes actually share) and only creates a new mesh-array BGL + new pipeline
|
|
571
|
+
// layout. This keeps the per-binding-shape SSOT in one place and avoids an
|
|
572
|
+
// alternate skin-only material BGL (the skin shader's group(0) and group(1)
|
|
573
|
+
// are byte-for-byte the standard-PBR contract).
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Build the PBR skin pipeline layout (4 slots `[view, material,
|
|
577
|
+
* mesh-array(2-entry), instances]`). View / material / instances BGLs are
|
|
578
|
+
* shared with the standard-PBR layout (passed in via `pbr` bundle); the only
|
|
579
|
+
* new BGL is the 2-entry mesh-array slot for `meshes` + `palette`.
|
|
580
|
+
*
|
|
581
|
+
* Throws on each `createBindGroupLayout` / `createPipelineLayout` Result
|
|
582
|
+
* failure -- the engine bootstrap path wraps the call in `runShimSyncStep`
|
|
583
|
+
* to fold the throw into the structured error pipe.
|
|
584
|
+
*/
|
|
585
|
+
export function buildPbrSkinLayouts(
|
|
586
|
+
device: PbrPipelineDevice,
|
|
587
|
+
caps: PbrCaps,
|
|
588
|
+
pbr: PbrPipelineLayoutBundle,
|
|
589
|
+
): PbrPipelineLayoutBundle {
|
|
590
|
+
// 2-entry mesh-array BGL: binding 0 meshes + binding 1 palette. Both
|
|
591
|
+
// dynamic-offset (palette window per-entity, like meshes window).
|
|
592
|
+
const skinMeshArrayBglRes = device.createBindGroupLayout(
|
|
593
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
594
|
+
kind: 'pbr-skin-mesh-array',
|
|
595
|
+
caps,
|
|
596
|
+
}),
|
|
597
|
+
);
|
|
598
|
+
if (!skinMeshArrayBglRes.ok) throw skinMeshArrayBglRes.error;
|
|
599
|
+
|
|
600
|
+
const layouts: readonly [BindGroupLayout, BindGroupLayout, BindGroupLayout, BindGroupLayout] = [
|
|
601
|
+
pbr.viewBgl,
|
|
602
|
+
pbr.materialBgl,
|
|
603
|
+
skinMeshArrayBglRes.value,
|
|
604
|
+
pbr.instancesBgl,
|
|
605
|
+
];
|
|
606
|
+
const pipelineLayoutRes = device.createPipelineLayout({
|
|
607
|
+
label: 'pbr-skin-pl',
|
|
608
|
+
bindGroupLayouts: layouts,
|
|
609
|
+
});
|
|
610
|
+
if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
|
|
611
|
+
|
|
612
|
+
return {
|
|
613
|
+
pipelineLayout: pipelineLayoutRes.value,
|
|
614
|
+
viewBgl: pbr.viewBgl,
|
|
615
|
+
materialBgl: pbr.materialBgl,
|
|
616
|
+
meshArrayBgl: skinMeshArrayBglRes.value,
|
|
617
|
+
instancesBgl: pbr.instancesBgl,
|
|
618
|
+
bindGroupLayouts: layouts,
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// ─── Unlit material BGL factory ─────────────────────────────────────────────
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Build a stand-alone 7-entry unlit material BGL. Round-4 D-5 keeps unlit
|
|
626
|
+
* material BG isolated from Skylight binding 7..13 -- unlit demos do not
|
|
627
|
+
* pay for IBL state. The unlit pipeline still binds material at slot 1,
|
|
628
|
+
* just with a 7-entry layout.
|
|
629
|
+
*
|
|
630
|
+
* Note: at the moment the runtime still routes both unlit + standard
|
|
631
|
+
* through a single 14-entry pipeline layout; the unlit material BG
|
|
632
|
+
* carries fallback identity resources at binding 7..13. This factory is
|
|
633
|
+
* exported as a future-proof seam for the moment when unlit demos own
|
|
634
|
+
* their own pipeline layout (t57 (e) test pins the contract today so the
|
|
635
|
+
* eventual split has a green target).
|
|
636
|
+
*/
|
|
637
|
+
export function buildUnlitMaterialBgl(device: PbrPipelineDevice): BindGroupLayout {
|
|
638
|
+
const res = device.createBindGroupLayout(
|
|
639
|
+
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'unlit-material' }),
|
|
640
|
+
);
|
|
641
|
+
if (!res.ok) throw res.error;
|
|
642
|
+
return res.value;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// ─── Material BG assembly helpers (unlit) ───────────────────────────────────
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Inputs for `buildUnlitMaterialBindGroupEntries`. The fields mirror the
|
|
649
|
+
* record-stage's local variables; isolating the assembler here lets t58
|
|
650
|
+
* (e) test exercise the contract without recreating the entire record
|
|
651
|
+
* stage.
|
|
652
|
+
*/
|
|
653
|
+
export interface UnlitMaterialBindGroupEntryInputs {
|
|
654
|
+
readonly materialUniform: Buffer;
|
|
655
|
+
readonly materialOffset: number;
|
|
656
|
+
readonly materialSize: number;
|
|
657
|
+
readonly defaultSampler: Sampler;
|
|
658
|
+
readonly baseColorView: TextureView;
|
|
659
|
+
readonly defaultWhiteView: TextureView;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Build the 7 BindGroupEntry values for the unlit material BG (binding
|
|
664
|
+
* 0..6). Output flows into `device.createBindGroup({ layout:
|
|
665
|
+
* unlitMaterialBgl, entries })`.
|
|
666
|
+
*/
|
|
667
|
+
export function buildUnlitMaterialBindGroupEntries(
|
|
668
|
+
inputs: UnlitMaterialBindGroupEntryInputs,
|
|
669
|
+
): BindGroupEntry[] {
|
|
670
|
+
return [
|
|
671
|
+
{
|
|
672
|
+
binding: 0,
|
|
673
|
+
resource: {
|
|
674
|
+
kind: 'buffer' as const,
|
|
675
|
+
value: {
|
|
676
|
+
buffer: inputs.materialUniform,
|
|
677
|
+
offset: inputs.materialOffset,
|
|
678
|
+
size: inputs.materialSize,
|
|
679
|
+
},
|
|
680
|
+
},
|
|
681
|
+
},
|
|
682
|
+
{ binding: 1, resource: { kind: 'sampler' as const, value: inputs.defaultSampler } },
|
|
683
|
+
{ binding: 2, resource: { kind: 'textureView' as const, value: inputs.baseColorView } },
|
|
684
|
+
{ binding: 3, resource: { kind: 'sampler' as const, value: inputs.defaultSampler } },
|
|
685
|
+
{ binding: 4, resource: { kind: 'textureView' as const, value: inputs.defaultWhiteView } },
|
|
686
|
+
{ binding: 5, resource: { kind: 'sampler' as const, value: inputs.defaultSampler } },
|
|
687
|
+
{ binding: 6, resource: { kind: 'textureView' as const, value: inputs.defaultWhiteView } },
|
|
688
|
+
];
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// Surface re-export so consumers can build a complete BindGroup pipeline
|
|
692
|
+
// without reaching into multiple modules.
|
|
693
|
+
export type { BindGroup };
|
|
694
|
+
|
|
695
|
+
// ─── feat-20260625 M3 / w10 — sprite-pass variantSet selector ────────────────
|
|
696
|
+
//
|
|
697
|
+
// Plan-strategy D-1 + D-4: when an entity carries `SpriteInstances` the
|
|
698
|
+
// sprite-pass record stage must pick the `PER_INSTANCE_REGION=true` sprite
|
|
699
|
+
// shader variant compiled in M2 (w7) so the WGSL `InstanceData` struct
|
|
700
|
+
// includes the per-instance `region: vec4<f32>` field and reads region from
|
|
701
|
+
// the interleaved 80B-per-instance buffer (not from the material UBO).
|
|
702
|
+
//
|
|
703
|
+
// Non-`SpriteInstances` sprite entities (e.g. the sprite-atlas demo) keep
|
|
704
|
+
// the default variant where `PER_INSTANCE_REGION` is undefined and the
|
|
705
|
+
// shader's `#else` branch reads region from material UBO — preserving
|
|
706
|
+
// existing behaviour (plan-strategy D-4 "pbr / unlit / sprite-atlas
|
|
707
|
+
// behaviour unchanged" / requirements Edge Cases).
|
|
708
|
+
//
|
|
709
|
+
// Variant set string format mirrors the existing `URP_PBR_VARIANT_SET` /
|
|
710
|
+
// HDRP variant set string idiom in `pipeline-spec.ts` (`+`-separated kv
|
|
711
|
+
// pairs); the record stage threads this string through the per-shader
|
|
712
|
+
// pipeline-cache key + lazy-build `getMaterialShaderPipeline` lookup.
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* variantSet string fired into the sprite-pass pipeline cache when the
|
|
716
|
+
* entity carries `SpriteInstances` (plan-strategy D-1 interleaved single
|
|
717
|
+
* buffer + D-4 axis on `sprite.wgsl`).
|
|
718
|
+
*
|
|
719
|
+
* bug-20260708 M2 (c): aligned with the canonical all-true variant key
|
|
720
|
+
* `''` — sprite's manifest emits `{PIR:true, SBA:true}` under the empty-
|
|
721
|
+
* string key (all variant axes true → canonical). The runtime's
|
|
722
|
+
* `getMaterialShaderPipeline` variant-substitution branch
|
|
723
|
+
* (`createRenderer.ts:1730`) resolves this via
|
|
724
|
+
* `findVariantByKey(msEntry, '')` returning the 5653B PIR=true variant.
|
|
725
|
+
* Combined with the `cacheKeyOf` sentinel `~` (bug-20260708 M2 (b)) this
|
|
726
|
+
* value produces a cache key distinct from the `variantSet=undefined`
|
|
727
|
+
* character/default path (which now resolves to the PIR=false 5575B boot-
|
|
728
|
+
* registered variant). Sprite pipeline layout routing is anchored via
|
|
729
|
+
* `LayoutKind='sprite-urp'` so `variantSet=''` here does NOT trigger the
|
|
730
|
+
* HDRP-layout branch of `selectPipelineLayoutForVariant` (research R-12
|
|
731
|
+
* flow; plan-strategy §4 R-1' guard).
|
|
732
|
+
*/
|
|
733
|
+
export const SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET = '';
|
|
734
|
+
|
|
735
|
+
// BglKind dispatch (M3 / D-13) — closed union of BGL shapes the runtime ships
|
|
736
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Closed union of bind-group-layout shapes the runtime constructs.
|
|
740
|
+
*
|
|
741
|
+
* Each kind names one physically distinct BGL the runtime has historically
|
|
742
|
+
* built by hand. {@link buildBindGroupLayoutDescriptor} dispatches on this
|
|
743
|
+
* union so every `device.createBindGroupLayout(...)` call site shares one
|
|
744
|
+
* SSOT for entries / labels (plan-strategy §3.2; D-13 round-2 decision).
|
|
745
|
+
*
|
|
746
|
+
* Three groups by derivation source:
|
|
747
|
+
* 1. Shader-derived (paramSchema reflection + injection chain):
|
|
748
|
+
* - `'pbr-material-merged'` — derived user region + Skylight 7 + lightmap 4
|
|
749
|
+
* - `'unlit-material'` — 7 entries: base PBR material only (no inject)
|
|
750
|
+
* - `'hdrp-7-slot'` — 7 entries (binding 0 + 3..8): HDRP cluster + SSAO group(2) BGL
|
|
751
|
+
* 2. Caps-driven literal shapes (no shader):
|
|
752
|
+
* - `'pbr-view'` — 10 entries: view UBO + lights + 6 shadow bindings
|
|
753
|
+
* (directional 3/4, point 5/6, cascade 7, spot atlas 8, spot
|
|
754
|
+
* lightViewProj matrices 9 — feat-20260625)
|
|
755
|
+
* - `'pbr-mesh-array'` — 1 entry: per-entity mesh SSBO (dynamic-offset)
|
|
756
|
+
* - `'pbr-instances'` — 1 entry: per-instance SSBO (no dynamic-offset)
|
|
757
|
+
* - `'pbr-skin-mesh-array'` — 2 entries: meshes + skin palette
|
|
758
|
+
* 3. Attachment-driven (fullscreen post-process):
|
|
759
|
+
* - `'fullscreen-post'` — 2 entries: input texture + sampler. The texture
|
|
760
|
+
* `sampleType` is derived from `spec.attachments` (plan §R3 fix):
|
|
761
|
+
* `'depth32float'` → `'depth'`; `'r32float'` → `'unfilterable-float'`;
|
|
762
|
+
* else → `'float'`.
|
|
763
|
+
* - `'fullscreen-post-with-params'` — 3 entries: the same texture@0 +
|
|
764
|
+
* sampler@1 as `'fullscreen-post'`, plus a `buffer@2` uniform for the
|
|
765
|
+
* per-frame params UBO (feat-20260621 D-2: `entry.params !== undefined`
|
|
766
|
+
* passes route here; the layout stays group(1), q3=B). `'fullscreen-post'`
|
|
767
|
+
* stays byte-identical so param-less consumers degrade with no change.
|
|
768
|
+
* - `'fullscreen-post-with-scene-depth-msaa'` — the depth-read layout with
|
|
769
|
+
* `texture.multisampled=true`, selected for a 4-sample scene depth target.
|
|
770
|
+
*/
|
|
771
|
+
export type BglKind =
|
|
772
|
+
| 'pbr-view'
|
|
773
|
+
| 'pbr-material-merged'
|
|
774
|
+
| 'pbr-mesh-array'
|
|
775
|
+
| 'pbr-instances'
|
|
776
|
+
| 'pbr-skin-mesh-array'
|
|
777
|
+
| 'unlit-material'
|
|
778
|
+
| 'hdrp-7-slot'
|
|
779
|
+
| 'fullscreen-post'
|
|
780
|
+
| 'fullscreen-post-with-params'
|
|
781
|
+
| 'fullscreen-post-with-scene-depth'
|
|
782
|
+
| 'fullscreen-post-with-scene-depth-msaa';
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Output shape of {@link buildBindGroupLayoutDescriptor}: matches the RHI
|
|
786
|
+
* `BindGroupLayoutDescriptor` (label + entries with `ExplicitUndefined`) so
|
|
787
|
+
* the result can be passed directly to `device.createBindGroupLayout(...)`.
|
|
788
|
+
*
|
|
789
|
+
* `entries` is a mutable `Array` to match `GPUBindGroupLayoutDescriptor`
|
|
790
|
+
* (WebGPU types declare it mutable). Callers MUST treat the array as
|
|
791
|
+
* read-only — the dispatcher freezes neither the array nor its entries
|
|
792
|
+
* for hot-path performance.
|
|
793
|
+
*/
|
|
794
|
+
export interface BindGroupLayoutDescriptorOutput {
|
|
795
|
+
readonly label: string | undefined;
|
|
796
|
+
readonly entries: GPUBindGroupLayoutEntry[];
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
/** Build the canonical HDRP group(2) bind-group layout. */
|
|
800
|
+
export function createHdrpBindGroupLayoutDescriptor(
|
|
801
|
+
storageBuffer: boolean = true,
|
|
802
|
+
): BindGroupLayoutDescriptor {
|
|
803
|
+
const meshBufType: GPUBufferBindingType = storageBuffer ? 'read-only-storage' : 'uniform';
|
|
804
|
+
const clusterBufType: GPUBufferBindingType = storageBuffer ? 'read-only-storage' : 'uniform';
|
|
805
|
+
return {
|
|
806
|
+
label: 'hdrp-unified-bgl-group2',
|
|
807
|
+
entries: [
|
|
808
|
+
{
|
|
809
|
+
binding: 0,
|
|
810
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
811
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
812
|
+
},
|
|
813
|
+
// Bindings 1 and 2 stay absent for the URP physical isolation gap.
|
|
814
|
+
{
|
|
815
|
+
binding: 3,
|
|
816
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
817
|
+
buffer: { type: clusterBufType, hasDynamicOffset: false },
|
|
818
|
+
},
|
|
819
|
+
{
|
|
820
|
+
binding: 4,
|
|
821
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
822
|
+
buffer: { type: clusterBufType, hasDynamicOffset: false },
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
binding: 5,
|
|
826
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
827
|
+
buffer: { type: clusterBufType, hasDynamicOffset: false },
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
binding: 6,
|
|
831
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
832
|
+
buffer: { type: 'uniform', hasDynamicOffset: false },
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
binding: 7,
|
|
836
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
837
|
+
texture: { sampleType: 'float', viewDimension: '2d', multisampled: false },
|
|
838
|
+
},
|
|
839
|
+
{
|
|
840
|
+
binding: 8,
|
|
841
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
842
|
+
sampler: { type: 'filtering' },
|
|
843
|
+
},
|
|
844
|
+
],
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Build a `GPUBindGroupLayoutDescriptor` from a PipelineSpec, dispatching on
|
|
850
|
+
* `options.kind` to one of 9 closed BGL shapes (D-13 round-2).
|
|
851
|
+
*
|
|
852
|
+
* Shader-derived kinds (`'pbr-material-merged'` / `'unlit-material'` /
|
|
853
|
+
* `'hdrp-7-slot'`) require `options.registry` to look up the shader entry
|
|
854
|
+
* and reflect its `paramSchema` via {@link deriveBglShapeFromShader}; they
|
|
855
|
+
* compose the per-entry injection chain (Skylight + lightmap for material;
|
|
856
|
+
* HDRP variantSet for cluster-forward).
|
|
857
|
+
*
|
|
858
|
+
* Caps-driven kinds (`'pbr-view'` / `'pbr-mesh-array'` / `'pbr-instances'` /
|
|
859
|
+
* `'pbr-skin-mesh-array'`) require `options.caps` for the storage-buffer
|
|
860
|
+
* vs uniform-buffer fallback (RhiCaps.storageBuffer; PBR feat-20260526 M3 /
|
|
861
|
+
* w9). They are wholly determined by the caps shape.
|
|
862
|
+
*
|
|
863
|
+
* Attachment-driven kind (`'fullscreen-post'`) reads
|
|
864
|
+
* `spec.attachments.depthFormat` and `spec.attachments.colorFormats[0]` to
|
|
865
|
+
* pick the texture binding's `sampleType` (R3 fix: `'depth32float'` → `'depth'`,
|
|
866
|
+
* `'r32float'` → `'unfilterable-float'`, else → `'float'`).
|
|
867
|
+
*
|
|
868
|
+
* @param spec - the pipeline spec (axis source for reflection / caps fallback)
|
|
869
|
+
* @param options.kind - which BGL shape to build (closed {@link BglKind} union)
|
|
870
|
+
* @param options.registry - ShaderCatalog for shader-derived kinds
|
|
871
|
+
* @param options.caps - caps shape for caps-driven kinds (storageBuffer)
|
|
872
|
+
* @returns a WebGPU bind-group-layout descriptor (entries + label)
|
|
873
|
+
* @see plan-strategy §3.2 · plan-decisions D-13 · requirements AC-02
|
|
874
|
+
*/
|
|
875
|
+
/**
|
|
876
|
+
* Resolve the material paramSchema for a per-shader user-region BGL derivation.
|
|
877
|
+
*
|
|
878
|
+
* Priority (D-1): explicit `options.materialParamSchema` > registry lookup of
|
|
879
|
+
* `spec.shader.id` > `undefined` (the user-region builder then falls back to
|
|
880
|
+
* the built-in standard-PBR 4-texture schema, whose user region is 9 entries).
|
|
881
|
+
*/
|
|
882
|
+
function resolveMaterialParamSchema(
|
|
883
|
+
spec: PipelineSpec,
|
|
884
|
+
options: { registry?: ShaderCatalog; materialParamSchema?: readonly ParamSchemaEntry[] },
|
|
885
|
+
): readonly ParamSchemaEntry[] | undefined {
|
|
886
|
+
if (options.materialParamSchema !== undefined) return options.materialParamSchema;
|
|
887
|
+
if (options.registry !== undefined) {
|
|
888
|
+
const lookup = options.registry.findMaterialArtifact(spec.shader.id);
|
|
889
|
+
if (lookup.ok) return lookup.value.paramSchema;
|
|
890
|
+
}
|
|
891
|
+
return undefined;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
export function buildBindGroupLayoutDescriptor(
|
|
895
|
+
spec: PipelineSpec,
|
|
896
|
+
options: {
|
|
897
|
+
kind: BglKind;
|
|
898
|
+
registry?: ShaderCatalog;
|
|
899
|
+
caps?: PbrCaps;
|
|
900
|
+
/**
|
|
901
|
+
* Material paramSchema for the per-shader user-region derivation
|
|
902
|
+
* (`'pbr-material-merged'` / `'unlit-material'`). When supplied it is the
|
|
903
|
+
* authoritative source for the user-region BGL shape (D-1); when omitted,
|
|
904
|
+
* `buildPbrMaterialUserRegionEntries` falls back to the built-in
|
|
905
|
+
* standard-PBR 4-texture schema (user region is 9 entries), so
|
|
906
|
+
* the caps-driven `buildPbrPipelineLayouts` seam keeps working unchanged.
|
|
907
|
+
* A registry + resolvable shader id takes precedence over this field.
|
|
908
|
+
*/
|
|
909
|
+
materialParamSchema?: readonly ParamSchemaEntry[];
|
|
910
|
+
},
|
|
911
|
+
): BindGroupLayoutDescriptorOutput {
|
|
912
|
+
switch (options.kind) {
|
|
913
|
+
case 'pbr-view': {
|
|
914
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
915
|
+
return {
|
|
916
|
+
label: 'pbr-view-bgl',
|
|
917
|
+
entries: buildPbrViewBglEntries(caps),
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
case 'pbr-mesh-array': {
|
|
921
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
922
|
+
const meshBufType: GPUBufferBindingType = caps.storageBuffer
|
|
923
|
+
? 'read-only-storage'
|
|
924
|
+
: 'uniform';
|
|
925
|
+
// sprite-lit's fragment stage does not read the mesh SSBO -- worldPos
|
|
926
|
+
// is carried through the VsOut interpolant. Visibility is kept widened
|
|
927
|
+
// to VERTEX|FRAGMENT because the BGL JSON is compared byte-identically
|
|
928
|
+
// across the sprite / sprite-lit / PBR pipelines that share this
|
|
929
|
+
// descriptor; narrowing here would change every sibling pipeline's
|
|
930
|
+
// BGL fingerprint. WebGPU rejects createRenderPipeline when a fragment
|
|
931
|
+
// stage accesses a binding whose BGL visibility excludes FRAGMENT --
|
|
932
|
+
// widening is permissive (validation-only, no perf cost).
|
|
933
|
+
return {
|
|
934
|
+
label: 'pbr-mesh-array-bgl',
|
|
935
|
+
entries: [
|
|
936
|
+
{
|
|
937
|
+
binding: 0,
|
|
938
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
939
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
940
|
+
},
|
|
941
|
+
],
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
case 'pbr-instances': {
|
|
945
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
946
|
+
const meshBufType: GPUBufferBindingType = caps.storageBuffer
|
|
947
|
+
? 'read-only-storage'
|
|
948
|
+
: 'uniform';
|
|
949
|
+
return {
|
|
950
|
+
label: 'pbr-instances-bgl',
|
|
951
|
+
entries: [
|
|
952
|
+
{
|
|
953
|
+
binding: 0,
|
|
954
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
955
|
+
buffer: { type: meshBufType, hasDynamicOffset: false },
|
|
956
|
+
},
|
|
957
|
+
],
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
case 'pbr-skin-mesh-array': {
|
|
961
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
962
|
+
const meshBufType: GPUBufferBindingType = caps.storageBuffer
|
|
963
|
+
? 'read-only-storage'
|
|
964
|
+
: 'uniform';
|
|
965
|
+
return {
|
|
966
|
+
label: 'pbr-skin-mesh-array-bgl',
|
|
967
|
+
entries: [
|
|
968
|
+
{
|
|
969
|
+
binding: 0,
|
|
970
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
971
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
972
|
+
},
|
|
973
|
+
{
|
|
974
|
+
binding: 1,
|
|
975
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
976
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
977
|
+
},
|
|
978
|
+
],
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
case 'pbr-material-merged': {
|
|
982
|
+
// Material BGL: per-shader user-region (derive(paramSchema).bglEntries)
|
|
983
|
+
// + IBL injection (7) + lightmap injection (4). The user-region size is
|
|
984
|
+
// the only variable; injection start = userRegion.length so a 4-texture
|
|
985
|
+
// custom schema shifts IBL/lightmap by one sampler/texture pair (D-1).
|
|
986
|
+
// For the built-in 4-texture standard-PBR schema this is 9 + 7 + 4 = 20.
|
|
987
|
+
//
|
|
988
|
+
// Schema source priority (D-1): explicit materialParamSchema option >
|
|
989
|
+
// registry lookup of spec.shader.id > built-in standard-PBR fallback.
|
|
990
|
+
const resolvedSchema = resolveMaterialParamSchema(spec, options);
|
|
991
|
+
const userRegion = buildPbrMaterialUserRegionEntries(resolvedSchema);
|
|
992
|
+
const afterIbl = [...userRegion, ...appendInjection(userRegion, 'ibl')];
|
|
993
|
+
const merged = [...afterIbl, ...appendInjection(afterIbl, 'lightmap')];
|
|
994
|
+
return {
|
|
995
|
+
label: 'pbr-material-skylight-bgl',
|
|
996
|
+
entries: merged,
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
case 'unlit-material': {
|
|
1000
|
+
// Unlit material BGL: per-shader user-region only. No IBL/lightmap
|
|
1001
|
+
// injection (D-5 round-4: unlit demos do not pay for IBL state).
|
|
1002
|
+
const resolvedSchema = resolveMaterialParamSchema(spec, options);
|
|
1003
|
+
return {
|
|
1004
|
+
label: 'unlit-material-bgl',
|
|
1005
|
+
entries: buildPbrMaterialUserRegionEntries(resolvedSchema),
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
1008
|
+
case 'hdrp-7-slot': {
|
|
1009
|
+
// HDRP unified BGL for group(2): 9 entries (binding 0 + 3..8). The
|
|
1010
|
+
// shape depends on caps.storageBuffer for the cluster-buffer fallback.
|
|
1011
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
1012
|
+
const desc = createHdrpBindGroupLayoutDescriptor(caps.storageBuffer);
|
|
1013
|
+
return {
|
|
1014
|
+
label: desc.label ?? 'hdrp-unified-bgl-group2',
|
|
1015
|
+
entries: [...(desc.entries ?? [])],
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
case 'fullscreen-post': {
|
|
1019
|
+
// Fullscreen post-process BGL: 2 entries (input texture + sampler).
|
|
1020
|
+
// R3 fix: derive sampleType from spec.attachments. Depth attachments
|
|
1021
|
+
// (depth32float) need `sampleType: 'depth'`; r32float needs
|
|
1022
|
+
// `'unfilterable-float'`; everything else (rgba8unorm-srgb, rgba16float,
|
|
1023
|
+
// bgra8unorm, …) is filterable `'float'`.
|
|
1024
|
+
return {
|
|
1025
|
+
label: 'fullscreen-post-bgl',
|
|
1026
|
+
entries: buildFullscreenPostInputEntries(spec),
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
case 'fullscreen-post-with-params': {
|
|
1030
|
+
// feat-20260621 D-2: the same input texture@0 + sampler@1 as
|
|
1031
|
+
// 'fullscreen-post', plus binding 2 = per-frame params UBO (uniform).
|
|
1032
|
+
// The first two entries reuse buildFullscreenPostInputEntries so the
|
|
1033
|
+
// sampleType derivation stays a single SSOT; 'fullscreen-post' is
|
|
1034
|
+
// untouched (param-less zero-regression, R-A7).
|
|
1035
|
+
return {
|
|
1036
|
+
label: 'fullscreen-post-with-params-bgl',
|
|
1037
|
+
entries: [
|
|
1038
|
+
...buildFullscreenPostInputEntries(spec),
|
|
1039
|
+
{
|
|
1040
|
+
binding: 2,
|
|
1041
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1042
|
+
buffer: { type: 'uniform' },
|
|
1043
|
+
},
|
|
1044
|
+
],
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
case 'fullscreen-post-with-scene-depth': {
|
|
1048
|
+
// plan-strategy D-3: 5-entry BGL for post-process passes that read the
|
|
1049
|
+
// camera scene depth. color@0 + sampler@1 reuse buildFullscreenPostInputEntries
|
|
1050
|
+
// (float+filtering for color). depthTex@3 uses `sampleType: 'depth'` and
|
|
1051
|
+
// `dimension: '2d'`; depthSampler@4 uses `type: 'non-filtering'` (nearest
|
|
1052
|
+
// + clamp-to-edge, D-2 — NOT comparison). params@2 is always present
|
|
1053
|
+
// (uniform) to avoid a 2x2 kind explosion per D-3.
|
|
1054
|
+
return {
|
|
1055
|
+
label: 'fullscreen-post-with-scene-depth-bgl',
|
|
1056
|
+
entries: [
|
|
1057
|
+
...buildFullscreenPostInputEntries(spec),
|
|
1058
|
+
{
|
|
1059
|
+
binding: 2,
|
|
1060
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1061
|
+
buffer: { type: 'uniform' },
|
|
1062
|
+
},
|
|
1063
|
+
{
|
|
1064
|
+
binding: 3,
|
|
1065
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1066
|
+
texture: { sampleType: 'depth', viewDimension: '2d' },
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
binding: 4,
|
|
1070
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1071
|
+
sampler: { type: 'non-filtering' },
|
|
1072
|
+
},
|
|
1073
|
+
],
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
case 'fullscreen-post-with-scene-depth-msaa': {
|
|
1077
|
+
return {
|
|
1078
|
+
label: 'fullscreen-post-with-scene-depth-msaa-bgl',
|
|
1079
|
+
entries: [
|
|
1080
|
+
...buildFullscreenPostInputEntries(spec),
|
|
1081
|
+
{
|
|
1082
|
+
binding: 2,
|
|
1083
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1084
|
+
buffer: { type: 'uniform' },
|
|
1085
|
+
},
|
|
1086
|
+
{
|
|
1087
|
+
binding: 3,
|
|
1088
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1089
|
+
texture: { sampleType: 'depth', viewDimension: '2d', multisampled: true },
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
binding: 4,
|
|
1093
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1094
|
+
sampler: { type: 'non-filtering' },
|
|
1095
|
+
},
|
|
1096
|
+
],
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* The shared texture@0 + sampler@1 entries for fullscreen post-process BGLs.
|
|
1104
|
+
* sampleType is derived from `spec.attachments` (R3 fix): depth attachments →
|
|
1105
|
+
* `'depth'` + `'comparison'` sampler; `'r32float'` → `'unfilterable-float'`;
|
|
1106
|
+
* else → `'float'` + `'filtering'`. Both `'fullscreen-post'` and
|
|
1107
|
+
* `'fullscreen-post-with-params'` reuse this so the derivation is one SSOT.
|
|
1108
|
+
*/
|
|
1109
|
+
function buildFullscreenPostInputEntries(spec: PipelineSpec): GPUBindGroupLayoutEntry[] {
|
|
1110
|
+
const inputFormat: GPUTextureFormat | undefined =
|
|
1111
|
+
spec.attachments.depthFormat ?? spec.attachments.colorFormats[0];
|
|
1112
|
+
const sampleType: GPUTextureSampleType =
|
|
1113
|
+
inputFormat === 'depth32float' ||
|
|
1114
|
+
inputFormat === 'depth24plus' ||
|
|
1115
|
+
inputFormat === 'depth24plus-stencil8' ||
|
|
1116
|
+
inputFormat === 'depth16unorm'
|
|
1117
|
+
? 'depth'
|
|
1118
|
+
: inputFormat === 'r32float'
|
|
1119
|
+
? 'unfilterable-float'
|
|
1120
|
+
: 'float';
|
|
1121
|
+
return [
|
|
1122
|
+
{
|
|
1123
|
+
binding: 0,
|
|
1124
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1125
|
+
texture: { sampleType, viewDimension: '2d' },
|
|
1126
|
+
},
|
|
1127
|
+
{
|
|
1128
|
+
binding: 1,
|
|
1129
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1130
|
+
sampler: {
|
|
1131
|
+
type: sampleType === 'depth' ? 'comparison' : 'filtering',
|
|
1132
|
+
},
|
|
1133
|
+
},
|
|
1134
|
+
];
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
// ══════════════════════════════════════════════════════════════════════════════
|