@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,1231 @@
|
|
|
1
|
+
// PipelineSpec 4-axis SSOT — single-file type + derive-fn + entrypoint + error model.
|
|
2
|
+
//
|
|
3
|
+
// feat-20260615-pipeline-spec-ssot M1: Establish PipelineSpec 4-axis type SSOT.
|
|
4
|
+
// M1-T1: type definitions + KNOWN_PASS_KINDS + PipelineSpecError closed union.
|
|
5
|
+
// M1-T2: 6 pure derive functions.
|
|
6
|
+
// M1-T3: deriveBglShapeFromShader helper.
|
|
7
|
+
// M1-T4: getOrBuildPipeline entrypoint + PipelineCache.
|
|
8
|
+
// M1-T5: 12 SPEC_CONST boot-time table.
|
|
9
|
+
//
|
|
10
|
+
// Design axiom: PipelineSpec is business-agnostic — no 'pbr' / 'sprite' / 'skybox'
|
|
11
|
+
// / 'fullscreen-*' strings appear on the type surface (plan-strategy D-7).
|
|
12
|
+
// BGL shape taxonomy lives in the ShaderCatalog implementation, not in spec.
|
|
13
|
+
//
|
|
14
|
+
// Charter alignment:
|
|
15
|
+
// F1: single file entrypoint (getOrBuildPipeline) — AI user indexes once
|
|
16
|
+
// P1: progressive disclosure — types at top, fns mid, error model bottom
|
|
17
|
+
// P3: explicit failure — closed PipelineSpecError union, no silent routes
|
|
18
|
+
// P4: consistent abstraction — 4-axis aligns with wgpu/Bevy/Three.js
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
deriveVertexBufferLayout,
|
|
22
|
+
deriveVertexLayoutProjection,
|
|
23
|
+
type VertexLayoutProjection,
|
|
24
|
+
} from '@forgeax/engine-geometry';
|
|
25
|
+
import {
|
|
26
|
+
err,
|
|
27
|
+
KNOWN_PASS_KINDS,
|
|
28
|
+
type MaterialRenderState,
|
|
29
|
+
ok,
|
|
30
|
+
type PrimitiveTopology,
|
|
31
|
+
type Result,
|
|
32
|
+
type VertexAttributeMap,
|
|
33
|
+
} from '@forgeax/engine-types';
|
|
34
|
+
import { VertexColorVariantConflictError } from './errors/render';
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
type BglKind,
|
|
38
|
+
type BindGroupLayoutDescriptorOutput,
|
|
39
|
+
buildBindGroupLayoutDescriptor,
|
|
40
|
+
createHdrpBindGroupLayoutDescriptor,
|
|
41
|
+
} from './pbr-pipeline';
|
|
42
|
+
|
|
43
|
+
// Re-export KNOWN_PASS_KINDS from @forgeax/engine-types for single-file discoverability (charter F1).
|
|
44
|
+
export { KNOWN_PASS_KINDS };
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The engine-owned deferred material target layout. `fs_gbuffer` returns
|
|
48
|
+
* normal+roughness, albedo+metallic, and emissive+AO in this order.
|
|
49
|
+
*/
|
|
50
|
+
export const DEFERRED_COLOR_FORMATS: readonly GPUTextureFormat[] = [
|
|
51
|
+
'rgba16float',
|
|
52
|
+
'rgba8unorm',
|
|
53
|
+
'rgba16float',
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
/** Derive the color attachment shape for a material pass kind. */
|
|
57
|
+
export function colorFormatsForPassKind(
|
|
58
|
+
passKind: string,
|
|
59
|
+
defaultColorFormat: GPUTextureFormat,
|
|
60
|
+
): readonly GPUTextureFormat[] {
|
|
61
|
+
if (passKindPolicyTable[passKind]?.shape === 'depth-only') return [];
|
|
62
|
+
if (passKind === 'deferred') return DEFERRED_COLOR_FORMATS;
|
|
63
|
+
return [defaultColorFormat];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
67
|
+
// PipelineSpec — immutable 4-axis data description (D-7: business-agnostic)
|
|
68
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Pipeline specification — immutable 4-axis data that completely determines
|
|
72
|
+
* what `device.createRenderPipeline(...)` does for a material shader pass.
|
|
73
|
+
*
|
|
74
|
+
* The 4 axes are:
|
|
75
|
+
* - `shader`: which WGSL source + material param schema + pass kind + variant set
|
|
76
|
+
* - `attachments`: color/depth/stencil formats + sample count (MSAA)
|
|
77
|
+
* - `geometry`: primitive topology + vertex attribute layout + index format
|
|
78
|
+
* - `renderState`: optional per-material render-state overrides (blend/cull/depth/stencil)
|
|
79
|
+
*
|
|
80
|
+
* Business-agnostic: no `'pbr'` / `'sprite'` / `'skybox'` strings pollute this
|
|
81
|
+
* type. BGL shape taxonomy is derived from `ShaderCatalog` internal reflection
|
|
82
|
+
* and never appears on the spec surface (plan-strategy D-7).
|
|
83
|
+
*
|
|
84
|
+
* @see plan-strategy §1 (4-axis) · D-7 (business-agnostic) · requirements §3.1
|
|
85
|
+
*/
|
|
86
|
+
export type { PipelineSpec } from './pipeline-spec-types';
|
|
87
|
+
|
|
88
|
+
import type { PipelineSpec } from './pipeline-spec-types';
|
|
89
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
90
|
+
// PipelineSpecError — closed union (5 + 2 transit codes)
|
|
91
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Closed union of PipelineSpec error codes.
|
|
95
|
+
*
|
|
96
|
+
* 5 business codes:
|
|
97
|
+
* - `'spec-inconsistent'`: axis mutual exclusion violated
|
|
98
|
+
* - `'unknown-pass-kind'`: passKind not in KNOWN_PASS_KINDS or registered
|
|
99
|
+
* - `'shader-bgl-reflection-mismatch'`: reflected BGL shape != shader declaration
|
|
100
|
+
* - `'attachment-format-incompatible'`: depth/stencil format vs PSO mismatch
|
|
101
|
+
* - `'unsupported-vertex-layout'`: vertex attributes don't match shader vs_main
|
|
102
|
+
*
|
|
103
|
+
* 2 transit codes:
|
|
104
|
+
* - `'pipeline-build-failed'`: wraps RhiError from device.createRenderPipeline
|
|
105
|
+
* - `'shader-not-registered'`: ShaderCatalog lookup returned undefined
|
|
106
|
+
*
|
|
107
|
+
* @see requirements §3.4 · AC-10 · charter P3
|
|
108
|
+
*/
|
|
109
|
+
export type PipelineSpecErrorCode =
|
|
110
|
+
| 'spec-inconsistent'
|
|
111
|
+
| 'unknown-pass-kind'
|
|
112
|
+
| 'shader-bgl-reflection-mismatch'
|
|
113
|
+
| 'attachment-format-incompatible'
|
|
114
|
+
| 'unsupported-vertex-layout'
|
|
115
|
+
| 'pipeline-build-failed'
|
|
116
|
+
| 'shader-not-registered';
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Structured pipeline-spec error — carries `.code` (discriminated union) +
|
|
120
|
+
* `.detail` (narrowed per code) + `.hint` (AI-user actionable prose).
|
|
121
|
+
*
|
|
122
|
+
* Inherits from `Error` so it integrates with existing catch blocks; the
|
|
123
|
+
* `.code` field enables exhaustive `switch` narrowing without string parsing
|
|
124
|
+
* (charter P3).
|
|
125
|
+
*/
|
|
126
|
+
export class PipelineSpecError extends Error {
|
|
127
|
+
readonly code: PipelineSpecErrorCode;
|
|
128
|
+
/**
|
|
129
|
+
* Narrowed detail payload — shape depends on `code`.
|
|
130
|
+
*
|
|
131
|
+
* - `'spec-inconsistent'`: `{ reason: string }`
|
|
132
|
+
* - `'unknown-pass-kind'`: `{ expected: readonly string[]; actual: string; hint?: string }`
|
|
133
|
+
* - `'shader-bgl-reflection-mismatch'`: `{ reflected: unknown; declared: unknown }`
|
|
134
|
+
* - `'attachment-format-incompatible'`: `{ reason: string; expected?: string; actual?: string }`
|
|
135
|
+
* - `'unsupported-vertex-layout'`: `{ specAttrs: string[]; shaderAttrs: string[] }`
|
|
136
|
+
* - `'pipeline-build-failed'`: `{ gpuMessage?: string; cause?: unknown }`
|
|
137
|
+
* - `'shader-not-registered'`: `{ shaderId: string; hint?: string }`
|
|
138
|
+
*/
|
|
139
|
+
readonly detail: Record<string, unknown>;
|
|
140
|
+
|
|
141
|
+
constructor(args: {
|
|
142
|
+
code: PipelineSpecErrorCode;
|
|
143
|
+
detail: Record<string, unknown>;
|
|
144
|
+
hint?: string;
|
|
145
|
+
}) {
|
|
146
|
+
super(
|
|
147
|
+
args.hint !== undefined
|
|
148
|
+
? `PipelineSpecError [${args.code}]: ${args.hint}`
|
|
149
|
+
: `PipelineSpecError [${args.code}]`,
|
|
150
|
+
);
|
|
151
|
+
this.name = 'PipelineSpecError';
|
|
152
|
+
this.code = args.code;
|
|
153
|
+
this.detail = args.detail;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
158
|
+
// renderStateHashSuffix — deterministic hash of MaterialRenderState
|
|
159
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Material snapshots hand the renderer immutable render-state objects. Keep
|
|
163
|
+
* the serialized suffix by object identity just like the vertex-layout
|
|
164
|
+
* digest below; the hot path otherwise sorts keys and serializes the same
|
|
165
|
+
* state once per renderable. Callers must not mutate a MaterialRenderState
|
|
166
|
+
* after passing it to the renderer (the PipelineSpec contract is immutable).
|
|
167
|
+
*/
|
|
168
|
+
const RENDER_STATE_HASH_CACHE = new WeakMap<object, string>();
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Deterministic hash suffix for MaterialRenderState (sorted keys, JSON.stringify).
|
|
172
|
+
*
|
|
173
|
+
* Returns `''` when `renderState` is `undefined` or has zero entries,
|
|
174
|
+
* preserving cache-key byte-compatibility with the pre-M1 shape.
|
|
175
|
+
*/
|
|
176
|
+
export function renderStateHash(renderState: MaterialRenderState | undefined): string {
|
|
177
|
+
if (renderState === undefined) return '';
|
|
178
|
+
const cached = RENDER_STATE_HASH_CACHE.get(renderState);
|
|
179
|
+
if (cached !== undefined) return cached;
|
|
180
|
+
const sorted = Object.keys(renderState).sort();
|
|
181
|
+
if (sorted.length === 0) {
|
|
182
|
+
RENDER_STATE_HASH_CACHE.set(renderState, '');
|
|
183
|
+
return '';
|
|
184
|
+
}
|
|
185
|
+
const payload: Record<string, unknown> = {};
|
|
186
|
+
for (const k of sorted) {
|
|
187
|
+
const v = renderState[k as keyof MaterialRenderState];
|
|
188
|
+
if (v !== undefined) payload[k] = v;
|
|
189
|
+
}
|
|
190
|
+
const result = `:${JSON.stringify(payload)}`;
|
|
191
|
+
RENDER_STATE_HASH_CACHE.set(renderState, result);
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
196
|
+
// 6 pure derive functions (M1-T2)
|
|
197
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Compute a deterministic cache key from a PipelineSpec.
|
|
201
|
+
*
|
|
202
|
+
* The key covers all 4 axes + BGL shape hash (derived from ShaderCatalog
|
|
203
|
+
* reflection via {@link deriveBglShapeFromShader}). Two specs that produce
|
|
204
|
+
* the same cache key MUST produce byte-identical PSO descriptors.
|
|
205
|
+
*
|
|
206
|
+
* Algorithm: concatenate each axis segment with `:` separators, hash the
|
|
207
|
+
* BGL shape for compactness, and emit a single cache-key string.
|
|
208
|
+
*
|
|
209
|
+
* @see plan-strategy §3.1 · requirements AC-02
|
|
210
|
+
*/
|
|
211
|
+
export function cacheKeyOf(spec: PipelineSpec): string {
|
|
212
|
+
const { shader, attachments, geometry, renderState } = spec;
|
|
213
|
+
const topoSegment = geometry.topology;
|
|
214
|
+
const stripSegment =
|
|
215
|
+
(topoSegment === 'line-strip' || topoSegment === 'triangle-strip') &&
|
|
216
|
+
geometry.stripIndexFormat !== undefined
|
|
217
|
+
? `:${geometry.stripIndexFormat}`
|
|
218
|
+
: '';
|
|
219
|
+
|
|
220
|
+
// The geometry owner publishes one immutable projection. Legacy callers may
|
|
221
|
+
// still provide only the map; derive the same projection at this boundary.
|
|
222
|
+
const vlDigest =
|
|
223
|
+
geometry.vertexLayoutProjection?.digest ??
|
|
224
|
+
deriveVertexLayoutProjection(geometry.vertexLayout).digest;
|
|
225
|
+
|
|
226
|
+
const uvSetCountSegment =
|
|
227
|
+
geometry.shaderUvSetCount !== undefined ? `:uvsc${geometry.shaderUvSetCount}` : '';
|
|
228
|
+
|
|
229
|
+
// bug-20260708 M2 (b): sentinel `~` distinguishes `variantSet=undefined`
|
|
230
|
+
// (no-variant / default-variant request) from canonical all-true key `''`
|
|
231
|
+
// (all variant axes true). Prior `?? ''` collapsed the two into the same
|
|
232
|
+
// cache key, causing the first-cached pipeline to win and unrelated
|
|
233
|
+
// variantSet requests to reuse its shader module (research R-11 / R-12).
|
|
234
|
+
// `~` (ASCII 0x7E) is a reserved sentinel char — no legitimate
|
|
235
|
+
// variantSet literal contains it; guarded by
|
|
236
|
+
// `pipeline-cache-keying.unit.test.ts` sentinel-conflict assertions.
|
|
237
|
+
const variantSegment = shader.variantSet === undefined ? '~' : shader.variantSet;
|
|
238
|
+
return (
|
|
239
|
+
[
|
|
240
|
+
shader.id,
|
|
241
|
+
shader.passKind,
|
|
242
|
+
variantSegment,
|
|
243
|
+
attachments.colorFormats.join(','),
|
|
244
|
+
attachments.depthFormat ?? '',
|
|
245
|
+
String(attachments.sampleCount),
|
|
246
|
+
topoSegment,
|
|
247
|
+
stripSegment,
|
|
248
|
+
`vl:${vlDigest}`,
|
|
249
|
+
renderStateHash(renderState),
|
|
250
|
+
].join(':') + uvSetCountSegment
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Reconcile the authored vertex-color shader axis with the geometry-owned
|
|
256
|
+
* projection. COLOR_0 is a geometry fact and cannot be selected independently
|
|
257
|
+
* by a material variant.
|
|
258
|
+
*/
|
|
259
|
+
export function variantSetFromVertexLayoutProjection(
|
|
260
|
+
projection: VertexLayoutProjection,
|
|
261
|
+
authoredVariantSet: string | undefined,
|
|
262
|
+
): Result<string, VertexColorVariantConflictError> {
|
|
263
|
+
const projected = projection.attributes.some((attribute) => attribute.key === 'color');
|
|
264
|
+
const axis = `VERTEX_COLOR_AVAILABLE=${projected ? 'true' : 'false'}`;
|
|
265
|
+
if (authoredVariantSet === undefined) return ok(axis);
|
|
266
|
+
if (projected && authoredVariantSet === '') return ok(authoredVariantSet);
|
|
267
|
+
|
|
268
|
+
const authoredParts = authoredVariantSet.split('+');
|
|
269
|
+
const authoredColorPart = authoredParts.find((part) =>
|
|
270
|
+
part.startsWith('VERTEX_COLOR_AVAILABLE='),
|
|
271
|
+
);
|
|
272
|
+
if (authoredColorPart === undefined) {
|
|
273
|
+
const parts = authoredParts.filter((part) => part.length > 0);
|
|
274
|
+
parts.push(axis);
|
|
275
|
+
return ok(parts.join('+'));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const authoredValue = authoredColorPart.slice('VERTEX_COLOR_AVAILABLE='.length);
|
|
279
|
+
const authored = authoredValue === 'true';
|
|
280
|
+
if ((authoredValue !== 'true' && authoredValue !== 'false') || authored !== projected) {
|
|
281
|
+
return err(new VertexColorVariantConflictError(authoredValue, projected));
|
|
282
|
+
}
|
|
283
|
+
const parts = authoredParts.filter(
|
|
284
|
+
(part) => part.length > 0 && !part.startsWith('VERTEX_COLOR_AVAILABLE='),
|
|
285
|
+
);
|
|
286
|
+
parts.push(axis);
|
|
287
|
+
return ok(parts.join('+'));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Build a `GPURenderPipelineDescriptor` from a PipelineSpec + shader modules.
|
|
292
|
+
*
|
|
293
|
+
* Pure derivation: same (spec, modules) always produces the same descriptor.
|
|
294
|
+
* Consumed by `getOrBuildPipeline` on cache miss; also available as a public
|
|
295
|
+
* helper for AI users who want the descriptor shape without going through the
|
|
296
|
+
* cache entrypoint.
|
|
297
|
+
*
|
|
298
|
+
* @param spec - the pipeline spec (4 axes)
|
|
299
|
+
* @param modules - `{ vertex: GPUShaderModule; fragment: GPUShaderModule }`
|
|
300
|
+
* @returns a complete WebGPU render-pipeline descriptor
|
|
301
|
+
* @see plan-strategy §3.2 · requirements AC-02
|
|
302
|
+
*/
|
|
303
|
+
export function buildPipelineDescriptor(
|
|
304
|
+
spec: PipelineSpec,
|
|
305
|
+
modules: {
|
|
306
|
+
vertex: unknown;
|
|
307
|
+
fragment: unknown;
|
|
308
|
+
vertexEntryPoint?: string;
|
|
309
|
+
fragmentEntryPoint?: string;
|
|
310
|
+
layout?: unknown;
|
|
311
|
+
},
|
|
312
|
+
): Record<string, unknown> {
|
|
313
|
+
// M2-T4: derive vertex buffers from spec.geometry.vertexLayout via
|
|
314
|
+
// deriveVertexBufferLayout (imported from vertex-attribute-layout.ts).
|
|
315
|
+
// Empty vertexLayout (fullscreen-post passes) → [].
|
|
316
|
+
// Non-empty (material shaders) → interleaved single-buffer layout.
|
|
317
|
+
//
|
|
318
|
+
// Entry points default to 'vs_main' / 'fs_main' for the 3 standard material
|
|
319
|
+
// shaders; fullscreen-post passes (skybox 'skybox_fs', SSAO 'vs_ssao' / 'fs_ssao_calc')
|
|
320
|
+
// pass custom entry points through the modules parameter.
|
|
321
|
+
//
|
|
322
|
+
// The optional `layout` field, when present, is forwarded to the descriptor
|
|
323
|
+
// so that the provider can detect it is already set and avoid overwriting.
|
|
324
|
+
|
|
325
|
+
const { attachments, geometry, renderState } = spec;
|
|
326
|
+
|
|
327
|
+
// A supplied projection is the geometry owner's immutable GPU descriptor.
|
|
328
|
+
// Do not re-derive it from a possibly stale attribute map.
|
|
329
|
+
const vertexBuffers =
|
|
330
|
+
geometry.vertexLayoutProjection === undefined
|
|
331
|
+
? deriveVertexBufferLayout(geometry.vertexLayout, {
|
|
332
|
+
...(geometry.shaderUvSetCount !== undefined
|
|
333
|
+
? { shaderUvSetCount: geometry.shaderUvSetCount }
|
|
334
|
+
: {}),
|
|
335
|
+
})
|
|
336
|
+
: geometry.vertexLayoutProjection.attributes.length === 0
|
|
337
|
+
? []
|
|
338
|
+
: [
|
|
339
|
+
{
|
|
340
|
+
arrayStride: geometry.vertexLayoutProjection.arrayStride,
|
|
341
|
+
attributes: geometry.vertexLayoutProjection.attributes.map(
|
|
342
|
+
({ shaderLocation, offset, format }) => ({
|
|
343
|
+
shaderLocation,
|
|
344
|
+
offset,
|
|
345
|
+
format,
|
|
346
|
+
}),
|
|
347
|
+
),
|
|
348
|
+
},
|
|
349
|
+
];
|
|
350
|
+
|
|
351
|
+
const descriptor: Record<string, unknown> = {
|
|
352
|
+
vertex: {
|
|
353
|
+
module: modules.vertex,
|
|
354
|
+
entryPoint: modules.vertexEntryPoint ?? 'vs_main',
|
|
355
|
+
buffers: vertexBuffers,
|
|
356
|
+
},
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// Fragment stage: absent for shadow-caster (depth-only), present for forward.
|
|
360
|
+
if (attachments.colorFormats.length > 0) {
|
|
361
|
+
descriptor.fragment = {
|
|
362
|
+
module: modules.fragment,
|
|
363
|
+
entryPoint: modules.fragmentEntryPoint ?? 'fs_main',
|
|
364
|
+
targets: attachments.colorFormats.map((fmt) => {
|
|
365
|
+
const target: Record<string, unknown> = { format: fmt };
|
|
366
|
+
if (renderState?.blend !== undefined) {
|
|
367
|
+
target.blend = renderState.blend;
|
|
368
|
+
}
|
|
369
|
+
return target;
|
|
370
|
+
}),
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Layout: forward if provided by caller (fullscreen-post passes set it).
|
|
375
|
+
if (modules.layout !== undefined) {
|
|
376
|
+
descriptor.layout = modules.layout;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Primitive state.
|
|
380
|
+
const primitive: Record<string, unknown> = {
|
|
381
|
+
topology: geometry.topology,
|
|
382
|
+
cullMode: renderState?.cullMode ?? 'back',
|
|
383
|
+
frontFace: renderState?.frontFace ?? 'ccw',
|
|
384
|
+
};
|
|
385
|
+
if (geometry.topology.endsWith('strip') && geometry.stripIndexFormat !== undefined) {
|
|
386
|
+
primitive.stripIndexFormat = geometry.stripIndexFormat;
|
|
387
|
+
}
|
|
388
|
+
descriptor.primitive = primitive;
|
|
389
|
+
|
|
390
|
+
// Depth-stencil state.
|
|
391
|
+
if (attachments.depthFormat !== undefined) {
|
|
392
|
+
const ds: Record<string, unknown> = {
|
|
393
|
+
format: attachments.depthFormat,
|
|
394
|
+
depthWriteEnabled: renderState?.depthWriteEnabled ?? true,
|
|
395
|
+
depthCompare: renderState?.depthCompare ?? 'less',
|
|
396
|
+
};
|
|
397
|
+
if (renderState?.stencilReadMask !== undefined) {
|
|
398
|
+
ds.stencilReadMask = renderState.stencilReadMask;
|
|
399
|
+
}
|
|
400
|
+
if (renderState?.stencilWriteMask !== undefined) {
|
|
401
|
+
ds.stencilWriteMask = renderState.stencilWriteMask;
|
|
402
|
+
}
|
|
403
|
+
if (renderState?.stencil !== undefined) {
|
|
404
|
+
ds.stencilFront = renderState.stencil;
|
|
405
|
+
ds.stencilBack = renderState.stencil;
|
|
406
|
+
}
|
|
407
|
+
descriptor.depthStencil = ds;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Multisample: absent for sampleCount=1 (undefined). For each value > 1,
|
|
411
|
+
// emit { count: sampleCount } so forward-compat sample counts (2, 8, …)
|
|
412
|
+
// flow through to the descriptor without requiring a type change.
|
|
413
|
+
if (attachments.sampleCount > 1) {
|
|
414
|
+
descriptor.multisample = {
|
|
415
|
+
count: attachments.sampleCount,
|
|
416
|
+
...(renderState?.alphaToCoverageEnabled === true && { alphaToCoverageEnabled: true }),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return descriptor;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
424
|
+
// passKindPolicyTable — closed map: passKind → attachment shape + default ops
|
|
425
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Default colour-attachment ops carried by a passKind policy.
|
|
429
|
+
*
|
|
430
|
+
* `clearValue` is `undefined` for `loadOp='load'` policies (no clear value
|
|
431
|
+
* is emitted into the descriptor when the prior contents are loaded).
|
|
432
|
+
*/
|
|
433
|
+
export interface AttachmentColorOps {
|
|
434
|
+
readonly loadOp: 'clear' | 'load';
|
|
435
|
+
readonly storeOp: 'store' | 'discard';
|
|
436
|
+
readonly clearValue: GPUColor | undefined;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Default depth-attachment ops carried by a passKind policy.
|
|
441
|
+
*
|
|
442
|
+
* `stencilLoadOp` / `stencilStoreOp` are absent on the policy itself — the
|
|
443
|
+
* stencil-op gate is auto-derived from `specAttachments.depthFormat` at call
|
|
444
|
+
* time (`'depth24plus-stencil8'` → `'clear'+'discard'`; everything else
|
|
445
|
+
* elides stencil ops). This collapses the R3/R5 stencil-op duplicates that
|
|
446
|
+
* previously lived inline at every forward-pass beginRenderPass call site.
|
|
447
|
+
*/
|
|
448
|
+
export interface AttachmentDepthOps {
|
|
449
|
+
readonly loadOp: 'clear' | 'load';
|
|
450
|
+
readonly storeOp: 'store' | 'discard';
|
|
451
|
+
readonly clearValue: number;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Attachment policy for a single passKind — declares the colour / depth shape
|
|
456
|
+
* the pass produces and the default load/store ops. Per-call-site overrides
|
|
457
|
+
* (skybox vs main forward differing on `colorLoadOp`, sprite-split forward
|
|
458
|
+
* differing on both `colorLoadOp` and `depthLoadOp`) flow through the
|
|
459
|
+
* `options` parameter of {@link buildBeginRenderPassDescriptor}.
|
|
460
|
+
*
|
|
461
|
+
* `shape` discriminator drives which attachment slots the descriptor emits:
|
|
462
|
+
* - `'depth-only'` → empty `colorAttachments[]`, `depthStencilAttachment` set
|
|
463
|
+
* - `'color-only'` → populated `colorAttachments[]`, no `depthStencilAttachment`
|
|
464
|
+
* - `'color-and-depth'` → both
|
|
465
|
+
*/
|
|
466
|
+
export interface PassKindAttachmentPolicy {
|
|
467
|
+
readonly shape: 'depth-only' | 'color-only' | 'color-and-depth';
|
|
468
|
+
readonly defaultColorOps: AttachmentColorOps | undefined;
|
|
469
|
+
readonly defaultDepthOps: AttachmentDepthOps | undefined;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Closed map of passKind → attachment policy. Covers the 10 attachment shapes
|
|
474
|
+
* the runtime ships (per plan-strategy M4):
|
|
475
|
+
*
|
|
476
|
+
* 1. `'forward'` — main geometry pass: color+depth(+stencil-gated)
|
|
477
|
+
* 2. `'deferred'` — HDRP G-Buffer geometry pass: MRT color+depth
|
|
478
|
+
* 3. `'shadow-caster'` — directional shadow caster: depth-only
|
|
479
|
+
* 4. `'point-shadow-caster'` — HDRP point-shadow caster: depth-only
|
|
480
|
+
* 5. `'skybox'` — fullscreen skybox: color-only clear/store
|
|
481
|
+
* 6. `'tonemap'` — HDR→LDR tonemap fullscreen: color-only clear/store
|
|
482
|
+
* 7. `'bloom-bright'` / `'bloom-blur'` — bloom downsample/blur: color-only
|
|
483
|
+
* clear/store
|
|
484
|
+
* 8. `'bloom-composite'` — bloom add-back: color-only load/store (NOT clear)
|
|
485
|
+
* 9. `'fxaa'` — fullscreen FXAA: color-only clear/store
|
|
486
|
+
* 10. `'post-process'` — generic fullscreen primitive (SSAO, render-graph
|
|
487
|
+
* fullscreen-post-process-pass dispatcher, M2 tonemap pre-warm slot):
|
|
488
|
+
* color-only clear/store
|
|
489
|
+
*
|
|
490
|
+
* Sprite-split forward sub-pass reuses the `'forward'` policy with
|
|
491
|
+
* `options.colorLoadOp='load'` + `options.depthLoadOp='load'`.
|
|
492
|
+
*
|
|
493
|
+
* Stencil-op gate is NOT in this table — it is derived from
|
|
494
|
+
* `specAttachments.depthFormat` inside the helper (depth24plus-stencil8
|
|
495
|
+
* → emit `stencilLoadOp:'clear' / stencilStoreOp:'discard'`).
|
|
496
|
+
*/
|
|
497
|
+
export const passKindPolicyTable: Readonly<Record<string, PassKindAttachmentPolicy>> = {
|
|
498
|
+
forward: {
|
|
499
|
+
shape: 'color-and-depth',
|
|
500
|
+
defaultColorOps: {
|
|
501
|
+
loadOp: 'clear',
|
|
502
|
+
storeOp: 'store',
|
|
503
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
504
|
+
},
|
|
505
|
+
defaultDepthOps: { loadOp: 'clear', storeOp: 'store', clearValue: 1 },
|
|
506
|
+
},
|
|
507
|
+
deferred: {
|
|
508
|
+
shape: 'color-and-depth',
|
|
509
|
+
defaultColorOps: {
|
|
510
|
+
loadOp: 'clear',
|
|
511
|
+
storeOp: 'store',
|
|
512
|
+
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
|
513
|
+
},
|
|
514
|
+
defaultDepthOps: { loadOp: 'clear', storeOp: 'store', clearValue: 1 },
|
|
515
|
+
},
|
|
516
|
+
'shadow-caster': {
|
|
517
|
+
shape: 'depth-only',
|
|
518
|
+
defaultColorOps: undefined,
|
|
519
|
+
defaultDepthOps: { loadOp: 'clear', storeOp: 'store', clearValue: 1 },
|
|
520
|
+
},
|
|
521
|
+
'point-shadow-caster': {
|
|
522
|
+
shape: 'depth-only',
|
|
523
|
+
defaultColorOps: undefined,
|
|
524
|
+
defaultDepthOps: { loadOp: 'clear', storeOp: 'store', clearValue: 1 },
|
|
525
|
+
},
|
|
526
|
+
skybox: {
|
|
527
|
+
shape: 'color-only',
|
|
528
|
+
defaultColorOps: {
|
|
529
|
+
loadOp: 'clear',
|
|
530
|
+
storeOp: 'store',
|
|
531
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
532
|
+
},
|
|
533
|
+
defaultDepthOps: undefined,
|
|
534
|
+
},
|
|
535
|
+
tonemap: {
|
|
536
|
+
shape: 'color-only',
|
|
537
|
+
defaultColorOps: {
|
|
538
|
+
loadOp: 'clear',
|
|
539
|
+
storeOp: 'store',
|
|
540
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
541
|
+
},
|
|
542
|
+
defaultDepthOps: undefined,
|
|
543
|
+
},
|
|
544
|
+
'bloom-bright': {
|
|
545
|
+
shape: 'color-only',
|
|
546
|
+
defaultColorOps: {
|
|
547
|
+
loadOp: 'clear',
|
|
548
|
+
storeOp: 'store',
|
|
549
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
550
|
+
},
|
|
551
|
+
defaultDepthOps: undefined,
|
|
552
|
+
},
|
|
553
|
+
'bloom-blur': {
|
|
554
|
+
shape: 'color-only',
|
|
555
|
+
defaultColorOps: {
|
|
556
|
+
loadOp: 'clear',
|
|
557
|
+
storeOp: 'store',
|
|
558
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
559
|
+
},
|
|
560
|
+
defaultDepthOps: undefined,
|
|
561
|
+
},
|
|
562
|
+
'bloom-composite': {
|
|
563
|
+
shape: 'color-only',
|
|
564
|
+
defaultColorOps: {
|
|
565
|
+
loadOp: 'load',
|
|
566
|
+
storeOp: 'store',
|
|
567
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
568
|
+
},
|
|
569
|
+
defaultDepthOps: undefined,
|
|
570
|
+
},
|
|
571
|
+
fxaa: {
|
|
572
|
+
shape: 'color-only',
|
|
573
|
+
defaultColorOps: {
|
|
574
|
+
loadOp: 'clear',
|
|
575
|
+
storeOp: 'store',
|
|
576
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
577
|
+
},
|
|
578
|
+
defaultDepthOps: undefined,
|
|
579
|
+
},
|
|
580
|
+
'post-process': {
|
|
581
|
+
shape: 'color-only',
|
|
582
|
+
defaultColorOps: {
|
|
583
|
+
loadOp: 'clear',
|
|
584
|
+
storeOp: 'store',
|
|
585
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
586
|
+
},
|
|
587
|
+
defaultDepthOps: undefined,
|
|
588
|
+
},
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Build a `GPURenderPassDescriptor` from spec attachments + resolved views +
|
|
593
|
+
* a passKind policy lookup.
|
|
594
|
+
*
|
|
595
|
+
* The helper is the single SSOT for `device.beginRenderPass(...)` descriptor
|
|
596
|
+
* shape — every record-stage call site routes through it (plan-strategy M4
|
|
597
|
+
* AC-06). It dispatches on `passKindPolicyTable[passKind]` to pick the
|
|
598
|
+
* attachment shape (depth-only / color-only / color-and-depth) and applies
|
|
599
|
+
* default color/depth load+store ops; per-call overrides (sprite-split's
|
|
600
|
+
* `loadOp:'load'`, main pass's dynamic `mainColorLoadOp`, skybox's specific
|
|
601
|
+
* clearColor) flow through `options`.
|
|
602
|
+
*
|
|
603
|
+
* Stencil-op gate is auto-derived from `specAttachments.depthFormat`:
|
|
604
|
+
* - `'depth24plus-stencil8'` → emits `stencilLoadOp:'clear', stencilStoreOp:'discard'`
|
|
605
|
+
* - every other depth format → omits stencil ops entirely
|
|
606
|
+
*
|
|
607
|
+
* This collapses the R3/R5 stencil-op duplicates that previously lived inline
|
|
608
|
+
* at every forward-pass beginRenderPass site.
|
|
609
|
+
*
|
|
610
|
+
* @param specAttachments - the attachments axis from a PipelineSpec
|
|
611
|
+
* @param viewBindings - resolved texture views: `{ colorViews, depthView?, resolveTargets? }`
|
|
612
|
+
* @param passKind - one of the keys in {@link passKindPolicyTable}
|
|
613
|
+
* @param options - per-call ops overrides (loadOp / clearValue / label)
|
|
614
|
+
* @returns a WebGPU render-pass descriptor
|
|
615
|
+
* @throws PipelineSpecError(`'unknown-pass-kind'`) when passKind is not registered
|
|
616
|
+
* @see plan-strategy M4 · requirements AC-06
|
|
617
|
+
*/
|
|
618
|
+
export function buildBeginRenderPassDescriptor(
|
|
619
|
+
specAttachments: PipelineSpec['attachments'],
|
|
620
|
+
viewBindings: {
|
|
621
|
+
readonly colorViews: readonly unknown[];
|
|
622
|
+
readonly resolveTargets?: readonly (unknown | undefined)[];
|
|
623
|
+
readonly depthView?: unknown;
|
|
624
|
+
},
|
|
625
|
+
passKind: string,
|
|
626
|
+
options?: {
|
|
627
|
+
readonly colorLoadOp?: 'clear' | 'load';
|
|
628
|
+
readonly colorStoreOp?: 'store' | 'discard';
|
|
629
|
+
readonly clearColor?: GPUColor;
|
|
630
|
+
readonly depthLoadOp?: 'clear' | 'load';
|
|
631
|
+
readonly depthStoreOp?: 'store' | 'discard';
|
|
632
|
+
readonly label?: string;
|
|
633
|
+
},
|
|
634
|
+
): Record<string, unknown> {
|
|
635
|
+
const policy = passKindPolicyTable[passKind];
|
|
636
|
+
if (policy === undefined) {
|
|
637
|
+
throw new PipelineSpecError({
|
|
638
|
+
code: 'unknown-pass-kind',
|
|
639
|
+
detail: { expected: Object.keys(passKindPolicyTable), actual: passKind },
|
|
640
|
+
hint: `passKind '${passKind}' is not in passKindPolicyTable; register an attachment policy or pick an existing one (e.g. 'post-process' for fullscreen-quad passes)`,
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
const out: Record<string, unknown> = {};
|
|
645
|
+
if (options?.label !== undefined) {
|
|
646
|
+
out.label = options.label;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// Colour attachments: depth-only → empty array; otherwise iterate colorViews
|
|
650
|
+
// and apply policy default ops + per-call overrides. resolveTargets[i] === undefined
|
|
651
|
+
// means "no resolve for this slot"; only present slots emit a `resolveTarget`.
|
|
652
|
+
if (policy.shape === 'depth-only') {
|
|
653
|
+
out.colorAttachments = [];
|
|
654
|
+
} else {
|
|
655
|
+
const colorOps = policy.defaultColorOps;
|
|
656
|
+
if (colorOps === undefined) {
|
|
657
|
+
throw new PipelineSpecError({
|
|
658
|
+
code: 'spec-inconsistent',
|
|
659
|
+
detail: {
|
|
660
|
+
reason: 'policy-shape-color-without-colorOps',
|
|
661
|
+
actual: passKind,
|
|
662
|
+
},
|
|
663
|
+
hint: `passKind '${passKind}' has shape='${policy.shape}' but no defaultColorOps; fix passKindPolicyTable entry`,
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
const loadOp = options?.colorLoadOp ?? colorOps.loadOp;
|
|
667
|
+
const storeOp = options?.colorStoreOp ?? colorOps.storeOp;
|
|
668
|
+
const clearValue = options?.clearColor ?? colorOps.clearValue;
|
|
669
|
+
|
|
670
|
+
out.colorAttachments = viewBindings.colorViews.map((view, i) => {
|
|
671
|
+
const slot: Record<string, unknown> = {
|
|
672
|
+
view,
|
|
673
|
+
loadOp,
|
|
674
|
+
storeOp,
|
|
675
|
+
};
|
|
676
|
+
const resolveTarget = viewBindings.resolveTargets?.[i];
|
|
677
|
+
if (resolveTarget !== undefined) {
|
|
678
|
+
slot.resolveTarget = resolveTarget;
|
|
679
|
+
}
|
|
680
|
+
// Emit clearValue only when load is 'clear' AND a value is available.
|
|
681
|
+
if (loadOp === 'clear' && clearValue !== undefined) {
|
|
682
|
+
slot.clearValue = clearValue;
|
|
683
|
+
}
|
|
684
|
+
return slot;
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Depth-stencil attachment: emitted iff policy declares depth ops AND
|
|
689
|
+
// the spec carries a depthFormat. Stencil ops auto-derived from format.
|
|
690
|
+
if (policy.shape !== 'color-only' && policy.defaultDepthOps !== undefined) {
|
|
691
|
+
const dOps = policy.defaultDepthOps;
|
|
692
|
+
const depthLoadOp = options?.depthLoadOp ?? dOps.loadOp;
|
|
693
|
+
const depthStoreOp = options?.depthStoreOp ?? dOps.storeOp;
|
|
694
|
+
const ds: Record<string, unknown> = {
|
|
695
|
+
view: viewBindings.depthView,
|
|
696
|
+
depthLoadOp,
|
|
697
|
+
depthStoreOp,
|
|
698
|
+
};
|
|
699
|
+
if (depthLoadOp === 'clear') {
|
|
700
|
+
ds.depthClearValue = dOps.clearValue;
|
|
701
|
+
}
|
|
702
|
+
// Stencil-op gate: only depth24plus-stencil8 carries a stencil aspect.
|
|
703
|
+
if (specAttachments.depthFormat === 'depth24plus-stencil8') {
|
|
704
|
+
ds.stencilClearValue = 0;
|
|
705
|
+
ds.stencilLoadOp = 'clear';
|
|
706
|
+
ds.stencilStoreOp = 'discard';
|
|
707
|
+
}
|
|
708
|
+
out.depthStencilAttachment = ds;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
return out;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Validate a PipelineSpec before attempting to build.
|
|
716
|
+
*
|
|
717
|
+
* Fail-fast checks (charter P5) covering axis mutual-exclusion rules.
|
|
718
|
+
* Returns `Result<void, PipelineSpecError>` — ok for valid specs,
|
|
719
|
+
* err with structured code + detail for invalid ones.
|
|
720
|
+
*
|
|
721
|
+
* Checks:
|
|
722
|
+
* 1. `sampleCount=4` with empty `colorFormats` → `'spec-inconsistent'`
|
|
723
|
+
* 2. Pass kind not in `KNOWN_PASS_KINDS` → `'unknown-pass-kind'`
|
|
724
|
+
* 3. `depthFormat` undefined but `renderState` implies depth testing →
|
|
725
|
+
* `'attachment-format-incompatible'`
|
|
726
|
+
*
|
|
727
|
+
* @see plan-strategy §3.2 · requirements AC-02 · charter P5
|
|
728
|
+
*/
|
|
729
|
+
export function validateSpec(
|
|
730
|
+
spec: PipelineSpec,
|
|
731
|
+
):
|
|
732
|
+
| { ok: true }
|
|
733
|
+
| { ok: false; code: PipelineSpecErrorCode; detail: Record<string, unknown>; hint?: string } {
|
|
734
|
+
// Check 1: sampleCount=4 with empty colorFormats is inconsistent —
|
|
735
|
+
// multisample requires a colour target to resolve to.
|
|
736
|
+
if (spec.attachments.sampleCount === 4 && spec.attachments.colorFormats.length === 0) {
|
|
737
|
+
return {
|
|
738
|
+
ok: false,
|
|
739
|
+
code: 'spec-inconsistent',
|
|
740
|
+
detail: { reason: 'sample-count-format-incompatible' },
|
|
741
|
+
hint: 'sampleCount=4 requires at least one colorFormat; shadow-caster (depth-only) passes should use sampleCount=1',
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// Check 2: unknown pass kind
|
|
746
|
+
if (!KNOWN_PASS_KINDS.includes(spec.shader.passKind)) {
|
|
747
|
+
return {
|
|
748
|
+
ok: false,
|
|
749
|
+
code: 'unknown-pass-kind',
|
|
750
|
+
detail: { expected: KNOWN_PASS_KINDS, actual: spec.shader.passKind },
|
|
751
|
+
hint: `passKind '${spec.shader.passKind}' is not in KNOWN_PASS_KINDS; register custom pass kinds via ShaderCatalog`,
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Check 3: depth-testing renderState without a depthFormat
|
|
756
|
+
const depthOnly = passKindPolicyTable[spec.shader.passKind]?.shape === 'depth-only';
|
|
757
|
+
const depthRequired = !!spec.renderState?.depthCompare || depthOnly;
|
|
758
|
+
if (!spec.attachments.depthFormat && depthRequired) {
|
|
759
|
+
return {
|
|
760
|
+
ok: false,
|
|
761
|
+
code: 'attachment-format-incompatible',
|
|
762
|
+
detail: {
|
|
763
|
+
reason: 'depth-requirement-without-depth-format',
|
|
764
|
+
expected: 'depthFormat must be set when depth testing or a depth-only pass is requested',
|
|
765
|
+
actual: `depthFormat=${String(spec.attachments.depthFormat)}, depthCompare=${spec.renderState?.depthCompare}`,
|
|
766
|
+
},
|
|
767
|
+
hint: 'set attachments.depthFormat (e.g. depth24plus-stencil8 or depth32float) when renderState specifies depthCompare',
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
return { ok: true };
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
775
|
+
// PipelineCache — Map<string, RenderPipeline> container (D-12)
|
|
776
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Pipeline cache — Map from cacheKeyOf(spec) to opaque RenderPipeline handle.
|
|
780
|
+
*
|
|
781
|
+
* Constructed once at createRenderer boot time; shared across all call sites.
|
|
782
|
+
* Consumers call `getOrBuildPipeline(spec, deviceProvider, cache)` — the
|
|
783
|
+
* entrypoint does cache lookup internally; consumers never touch the Map
|
|
784
|
+
* directly.
|
|
785
|
+
*
|
|
786
|
+
* @see plan-strategy D-12 · requirements §3.2
|
|
787
|
+
*/
|
|
788
|
+
export type PipelineCache = Map<string, unknown>;
|
|
789
|
+
|
|
790
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
791
|
+
// getOrBuildPipeline — single entrypoint (D-12)
|
|
792
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Device factory interface consumed by {@link getOrBuildPipeline}.
|
|
796
|
+
*
|
|
797
|
+
* Slim abstraction: only `createRenderPipeline` is needed; the entrypoint
|
|
798
|
+
* does not depend on the full `RhiDevice` interface so it can be tested
|
|
799
|
+
* with a mock.
|
|
800
|
+
*/
|
|
801
|
+
export interface PipelineDeviceProvider {
|
|
802
|
+
createRenderPipeline(
|
|
803
|
+
descriptor: Record<string, unknown>,
|
|
804
|
+
): { ok: true; value: unknown } | { ok: false; error: unknown };
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Single entrypoint for obtaining a render pipeline from a spec.
|
|
809
|
+
*
|
|
810
|
+
* Cache-hit path: key = cacheKeyOf(spec), returns cached handle immediately.
|
|
811
|
+
* Cache-miss path: validates spec → builds descriptor → calls device.createRenderPipeline
|
|
812
|
+
* → caches result → returns handle.
|
|
813
|
+
* Build failure: throws PipelineSpecError (charter P3 fail-fast, no silent fallback).
|
|
814
|
+
*
|
|
815
|
+
* Pure function: same (spec, deviceProvider, cache) always produces the same result.
|
|
816
|
+
* Boot-time call site: createRenderer wires the real device; record-stage call site
|
|
817
|
+
* uses ctx.runtime.device (same entrypoint, same signature).
|
|
818
|
+
*
|
|
819
|
+
* @param spec - immutable 4-axis pipeline specification
|
|
820
|
+
* @param deviceProvider - factory with createRenderPipeline method
|
|
821
|
+
* @param cache - the PipelineCache (shared across boot + record stage)
|
|
822
|
+
* @returns a RenderPipeline handle (opaque, typed as unknown for M1)
|
|
823
|
+
* @throws PipelineSpecError on validation failure or build failure
|
|
824
|
+
* @see plan-strategy D-12 · requirements AC-03 · charter F1
|
|
825
|
+
*/
|
|
826
|
+
export function getOrBuildPipeline(
|
|
827
|
+
spec: PipelineSpec,
|
|
828
|
+
deviceProvider: PipelineDeviceProvider,
|
|
829
|
+
cache: PipelineCache,
|
|
830
|
+
modules?: {
|
|
831
|
+
vertex: unknown;
|
|
832
|
+
fragment: unknown;
|
|
833
|
+
vertexEntryPoint?: string;
|
|
834
|
+
fragmentEntryPoint?: string;
|
|
835
|
+
layout?: unknown;
|
|
836
|
+
},
|
|
837
|
+
): unknown {
|
|
838
|
+
const key = cacheKeyOf(spec);
|
|
839
|
+
|
|
840
|
+
// Cache hit — return immediately.
|
|
841
|
+
const cached = cache.get(key);
|
|
842
|
+
if (cached !== undefined) return cached;
|
|
843
|
+
|
|
844
|
+
// Cache miss — validate, build, cache, return.
|
|
845
|
+
const validation = validateSpec(spec);
|
|
846
|
+
if (!validation.ok) {
|
|
847
|
+
throw new PipelineSpecError({
|
|
848
|
+
code: validation.code,
|
|
849
|
+
detail: validation.detail,
|
|
850
|
+
...(validation.hint !== undefined ? { hint: validation.hint } : {}),
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
const descriptor = buildPipelineDescriptor(
|
|
855
|
+
spec,
|
|
856
|
+
modules ?? { vertex: undefined, fragment: undefined },
|
|
857
|
+
);
|
|
858
|
+
const result = deviceProvider.createRenderPipeline(descriptor);
|
|
859
|
+
|
|
860
|
+
if (!result.ok) {
|
|
861
|
+
throw new PipelineSpecError({
|
|
862
|
+
code: 'pipeline-build-failed',
|
|
863
|
+
detail: { cause: result.error },
|
|
864
|
+
hint: 'device.createRenderPipeline failed for spec; inspect gpuMessage on the error detail',
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
cache.set(key, result.value);
|
|
869
|
+
return result.value;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
873
|
+
// SPEC_CONST_TABLE — 12 boot-time pre-warm variants (M1-T5)
|
|
874
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
875
|
+
|
|
876
|
+
const PROCEDURAL_ATTR_LAYOUT: VertexAttributeMap = {
|
|
877
|
+
position: new Float32Array(0),
|
|
878
|
+
normal: new Float32Array(0),
|
|
879
|
+
uv: new Float32Array(0),
|
|
880
|
+
tangent: new Float32Array(0),
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
const HDR_FORMAT: GPUTextureFormat = 'rgba16float';
|
|
884
|
+
const DEPTH_DS: GPUTextureFormat = 'depth24plus-stencil8';
|
|
885
|
+
|
|
886
|
+
/**
|
|
887
|
+
* Default LDR view format used when callers ask for the SPEC_CONST table
|
|
888
|
+
* without an explicit swap-chain format. Kept for the backward-compatible
|
|
889
|
+
* `SPEC_CONST_TABLE` export consumed by unit tests that exercise the
|
|
890
|
+
* spec/cache-keying layer in isolation. Runtime callers always pass the
|
|
891
|
+
* format selected by `selectSwapChainFormat` (Channel 2 BGRA / Channel 3
|
|
892
|
+
* RGBA / dawn-node RGBA — see bug-20260615 fix-up note in `createRenderer`).
|
|
893
|
+
*/
|
|
894
|
+
const DEFAULT_LDR_FORMAT: GPUTextureFormat = 'bgra8unorm-srgb';
|
|
895
|
+
|
|
896
|
+
const TRI_GEOMETRY = {
|
|
897
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
898
|
+
stripIndexFormat: undefined,
|
|
899
|
+
vertexLayout: PROCEDURAL_ATTR_LAYOUT,
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
// feat-city-glb multi-UV tiling: the built-in standard PBR shader now declares
|
|
903
|
+
// UV sets @location(6..12), so naga reflects uvSetCount=8 for it and the URP
|
|
904
|
+
// record path threads `shaderUvSetCount: 8` into every standard-pbr spec
|
|
905
|
+
// (createRenderer.ts buildPipelineContext / getMaterialShaderPipeline).
|
|
906
|
+
// The boot-time prewarm must match on both axes: the PSO vertex layout includes
|
|
907
|
+
// all declared UV slots, and the cacheKey carries `:uvsc8`. For single-UV
|
|
908
|
+
// meshes deriveVertexBufferLayout clamp-to-last aliases every missing set onto
|
|
909
|
+
// the last mesh set (48-byte stride unchanged), so existing geometry remains
|
|
910
|
+
// byte-stable.
|
|
911
|
+
// unlit stays on TRI_GEOMETRY (its shader declares only @location(0..3)).
|
|
912
|
+
const TRI_GEOMETRY_PBR = {
|
|
913
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
914
|
+
stripIndexFormat: undefined,
|
|
915
|
+
vertexLayout: PROCEDURAL_ATTR_LAYOUT,
|
|
916
|
+
shaderUvSetCount: 8,
|
|
917
|
+
};
|
|
918
|
+
|
|
919
|
+
// M6 fix-up: URP-variant key string for the standard PBR shader. Mirrors the
|
|
920
|
+
// boot-time variantSet computed at createRenderer.ts step 1b when
|
|
921
|
+
// `isHdrpActive=false` and `storageBufferCapable=true` (the URP default
|
|
922
|
+
// surface). The URP record path requests this exact string at every
|
|
923
|
+
// `getMaterialShaderPipeline` call site, so seeding the table with these
|
|
924
|
+
// variants keeps the URP cache lookup hot from frame 1 instead of
|
|
925
|
+
// skip-drawing the first ~1 frames while the async compile resolves.
|
|
926
|
+
const URP_PBR_VARIANT_SET = 'CLUSTER_FORWARD_AVAILABLE=false+STORAGE_BUFFER_AVAILABLE=true';
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* Build the boot-time pre-warm table: 15 standard PipelineSpec variants.
|
|
930
|
+
*
|
|
931
|
+
* feat-20260625-refactor-sprite-as-transparent-mesh M3 / w14 (AC-12): the
|
|
932
|
+
* four `forgeax::default-sprite` entries (LDR S1 + LDR S4 + HDR S1 + HDR S4)
|
|
933
|
+
* are gone — sprite PSO lands lazily through the generic
|
|
934
|
+
* per-MaterialShader pipeline cache. Pre-feat count was 19; post-feat 15.
|
|
935
|
+
*
|
|
936
|
+
* Matrix:
|
|
937
|
+
* - 8 base material variants — {unlit, standard-pbr} x {LDR, HDR} x {S1, S4}
|
|
938
|
+
* - 4 URP-variant standard-pbr — standard-pbr (variantSet=URP_PBR_VARIANT_SET)
|
|
939
|
+
* x {LDR, HDR} x {S1, S4}; URP record path requests these specs by
|
|
940
|
+
* `getMaterialShaderPipeline` keying off `cacheKeyOf` so the boot-time
|
|
941
|
+
* prewarm seeds `materialShaderPipelineCache` and avoids a 1-frame
|
|
942
|
+
* async-compile skip-draw (M6 fix-up; see render-system-record.ts §URP)
|
|
943
|
+
* - 3 fullscreen-post — tonemap (LDR S1) + skybox (HDR S1, HDR S4)
|
|
944
|
+
*
|
|
945
|
+
* Total: 15. The URP variant is PBR-only because:
|
|
946
|
+
* - unlit URP record path passes `variantSet=undefined` (the no-variant
|
|
947
|
+
* boot-default entries already cover it; createRenderer.ts §unlitRsp)
|
|
948
|
+
* - sprite goes through `getMaterialShaderPipeline('forgeax::sprite', ...)`
|
|
949
|
+
* lazily at first transparent-LDR-split draw — no boot-time pre-warm.
|
|
950
|
+
* - HDRP variant (`variantSet=''` or compound `=true` form) is registered
|
|
951
|
+
* lazily when the clustered Standard profile activates, not at boot — adding clustered
|
|
952
|
+
* prewarm here would build PSOs against the URP layout (the boot-time
|
|
953
|
+
* `pbrModule` is the URP variant when `isHdrpActive=false`)
|
|
954
|
+
*
|
|
955
|
+
* `ldrViewFormat` parameterises the LDR color attachment format. Callers
|
|
956
|
+
* pass the runtime-resolved swap-chain view format (Channel 2 typically
|
|
957
|
+
* `bgra8unorm-srgb`; Channel 3 wgpu-wasm and dawn-node typically
|
|
958
|
+
* `rgba8unorm-srgb`). Hard-coding `bgra8unorm-srgb` at module load made
|
|
959
|
+
* the pre-warmed PSOs incompatible with the actual RenderPass color
|
|
960
|
+
* attachment on Channel 3 / dawn-node, producing whole-commandBuffer
|
|
961
|
+
* invalid errors on every frame (bug-20260615 fix-up — see
|
|
962
|
+
* `createRenderer` boot-time pre-warm site).
|
|
963
|
+
*
|
|
964
|
+
* Fullscreen passes (fxaa / bloom x 3 / SSAO x 2) are lazy-build — they
|
|
965
|
+
* use the same getOrBuildPipeline entrypoint but are not in this table.
|
|
966
|
+
*
|
|
967
|
+
* @see plan-strategy D-4 · research R-D4 · requirements AC-16
|
|
968
|
+
* @see bug-20260612-webgpu-canvas-format-prefer-bgra-shipped (same trap shape)
|
|
969
|
+
*/
|
|
970
|
+
export function buildSpecConstTable(
|
|
971
|
+
ldrViewFormat: GPUTextureFormat,
|
|
972
|
+
): readonly Readonly<PipelineSpec>[] {
|
|
973
|
+
const TRI_ATTACHMENTS_LDR_S1 = {
|
|
974
|
+
colorFormats: [ldrViewFormat],
|
|
975
|
+
depthFormat: DEPTH_DS,
|
|
976
|
+
sampleCount: 1 as const,
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
const TRI_ATTACHMENTS_LDR_S4 = {
|
|
980
|
+
colorFormats: [ldrViewFormat],
|
|
981
|
+
depthFormat: DEPTH_DS,
|
|
982
|
+
sampleCount: 4 as const,
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
// feat-20260625-refactor-sprite-as-transparent-mesh M3 / w14 (AC-12 / D-7):
|
|
986
|
+
// SPRITE_ATTACHMENTS_LDR_S1 / S4 (the dedicated non-srgb storage-format
|
|
987
|
+
// attachments the sprite spec entries consumed) were deleted alongside the
|
|
988
|
+
// four `forgeax::default-sprite` SPEC_CONST entries. The bgra8unorm storage
|
|
989
|
+
// format itself is still enforced at the LDR sprite sub-pass attachment
|
|
990
|
+
// level (the WebGPU pipeline `colorFormats` derive from the actual render
|
|
991
|
+
// pass attachment view, which is built off `pipelineState.format` =
|
|
992
|
+
// swap-chain storage format — see `render-system-record.ts` LDR split
|
|
993
|
+
// beginRenderPass call). The triggering source migrated from the
|
|
994
|
+
// spec-table id to `material.transparent` (derived by the extract stage
|
|
995
|
+
// from `passes[0].renderState.blend !== undefined`, the
|
|
996
|
+
// post-feat-20260626-collapse SSOT; w7 onwards).
|
|
997
|
+
|
|
998
|
+
const TRI_ATTACHMENTS_HDR_S1 = {
|
|
999
|
+
colorFormats: [HDR_FORMAT],
|
|
1000
|
+
depthFormat: DEPTH_DS,
|
|
1001
|
+
sampleCount: 1 as const,
|
|
1002
|
+
};
|
|
1003
|
+
|
|
1004
|
+
const TRI_ATTACHMENTS_HDR_S4 = {
|
|
1005
|
+
colorFormats: [HDR_FORMAT],
|
|
1006
|
+
depthFormat: DEPTH_DS,
|
|
1007
|
+
sampleCount: 4 as const,
|
|
1008
|
+
};
|
|
1009
|
+
|
|
1010
|
+
return [
|
|
1011
|
+
// unlit LDR S1
|
|
1012
|
+
{
|
|
1013
|
+
shader: { id: 'forgeax::default-unlit', passKind: 'forward', variantSet: undefined },
|
|
1014
|
+
attachments: TRI_ATTACHMENTS_LDR_S1,
|
|
1015
|
+
geometry: TRI_GEOMETRY,
|
|
1016
|
+
renderState: undefined,
|
|
1017
|
+
},
|
|
1018
|
+
// unlit LDR S4
|
|
1019
|
+
{
|
|
1020
|
+
shader: { id: 'forgeax::default-unlit', passKind: 'forward', variantSet: undefined },
|
|
1021
|
+
attachments: TRI_ATTACHMENTS_LDR_S4,
|
|
1022
|
+
geometry: TRI_GEOMETRY,
|
|
1023
|
+
renderState: undefined,
|
|
1024
|
+
},
|
|
1025
|
+
// unlit HDR S1
|
|
1026
|
+
{
|
|
1027
|
+
shader: { id: 'forgeax::default-unlit', passKind: 'forward', variantSet: undefined },
|
|
1028
|
+
attachments: TRI_ATTACHMENTS_HDR_S1,
|
|
1029
|
+
geometry: TRI_GEOMETRY,
|
|
1030
|
+
renderState: undefined,
|
|
1031
|
+
},
|
|
1032
|
+
// unlit HDR S4
|
|
1033
|
+
{
|
|
1034
|
+
shader: { id: 'forgeax::default-unlit', passKind: 'forward', variantSet: undefined },
|
|
1035
|
+
attachments: TRI_ATTACHMENTS_HDR_S4,
|
|
1036
|
+
geometry: TRI_GEOMETRY,
|
|
1037
|
+
renderState: undefined,
|
|
1038
|
+
},
|
|
1039
|
+
// standard LDR S1
|
|
1040
|
+
{
|
|
1041
|
+
shader: { id: 'forgeax::default-standard-pbr', passKind: 'forward', variantSet: undefined },
|
|
1042
|
+
attachments: TRI_ATTACHMENTS_LDR_S1,
|
|
1043
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1044
|
+
renderState: undefined,
|
|
1045
|
+
},
|
|
1046
|
+
// standard LDR S4
|
|
1047
|
+
{
|
|
1048
|
+
shader: { id: 'forgeax::default-standard-pbr', passKind: 'forward', variantSet: undefined },
|
|
1049
|
+
attachments: TRI_ATTACHMENTS_LDR_S4,
|
|
1050
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1051
|
+
renderState: undefined,
|
|
1052
|
+
},
|
|
1053
|
+
// standard HDR S1
|
|
1054
|
+
{
|
|
1055
|
+
shader: { id: 'forgeax::default-standard-pbr', passKind: 'forward', variantSet: undefined },
|
|
1056
|
+
attachments: TRI_ATTACHMENTS_HDR_S1,
|
|
1057
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1058
|
+
renderState: undefined,
|
|
1059
|
+
},
|
|
1060
|
+
// standard HDR S4
|
|
1061
|
+
{
|
|
1062
|
+
shader: { id: 'forgeax::default-standard-pbr', passKind: 'forward', variantSet: undefined },
|
|
1063
|
+
attachments: TRI_ATTACHMENTS_HDR_S4,
|
|
1064
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1065
|
+
renderState: undefined,
|
|
1066
|
+
},
|
|
1067
|
+
|
|
1068
|
+
// ── M6 fix-up: URP-variant standard-pbr prewarm ─────────────────────────
|
|
1069
|
+
// URP record path (`getMaterialShaderPipeline`) requests
|
|
1070
|
+
// `variantSet=URP_PBR_VARIANT_SET` for standard-shading entities; pre-M6
|
|
1071
|
+
// the silent `selectStandardFallbackPipeline` shim served the no-variant
|
|
1072
|
+
// boot prewarm during the 1-frame async-compile warmup. With M6's
|
|
1073
|
+
// explicit-failure surface, those URP requests must hit the boot prewarm
|
|
1074
|
+
// by their own variantSet — these 4 entries close that gap.
|
|
1075
|
+
|
|
1076
|
+
// standard PBR URP LDR S1
|
|
1077
|
+
{
|
|
1078
|
+
shader: {
|
|
1079
|
+
id: 'forgeax::default-standard-pbr',
|
|
1080
|
+
passKind: 'forward',
|
|
1081
|
+
variantSet: URP_PBR_VARIANT_SET,
|
|
1082
|
+
},
|
|
1083
|
+
attachments: TRI_ATTACHMENTS_LDR_S1,
|
|
1084
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1085
|
+
renderState: undefined,
|
|
1086
|
+
},
|
|
1087
|
+
// standard PBR URP LDR S4
|
|
1088
|
+
{
|
|
1089
|
+
shader: {
|
|
1090
|
+
id: 'forgeax::default-standard-pbr',
|
|
1091
|
+
passKind: 'forward',
|
|
1092
|
+
variantSet: URP_PBR_VARIANT_SET,
|
|
1093
|
+
},
|
|
1094
|
+
attachments: TRI_ATTACHMENTS_LDR_S4,
|
|
1095
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1096
|
+
renderState: undefined,
|
|
1097
|
+
},
|
|
1098
|
+
// standard PBR URP HDR S1
|
|
1099
|
+
{
|
|
1100
|
+
shader: {
|
|
1101
|
+
id: 'forgeax::default-standard-pbr',
|
|
1102
|
+
passKind: 'forward',
|
|
1103
|
+
variantSet: URP_PBR_VARIANT_SET,
|
|
1104
|
+
},
|
|
1105
|
+
attachments: TRI_ATTACHMENTS_HDR_S1,
|
|
1106
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1107
|
+
renderState: undefined,
|
|
1108
|
+
},
|
|
1109
|
+
// standard PBR URP HDR S4
|
|
1110
|
+
{
|
|
1111
|
+
shader: {
|
|
1112
|
+
id: 'forgeax::default-standard-pbr',
|
|
1113
|
+
passKind: 'forward',
|
|
1114
|
+
variantSet: URP_PBR_VARIANT_SET,
|
|
1115
|
+
},
|
|
1116
|
+
attachments: TRI_ATTACHMENTS_HDR_S4,
|
|
1117
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1118
|
+
renderState: undefined,
|
|
1119
|
+
},
|
|
1120
|
+
|
|
1121
|
+
// feat-20260625-refactor-sprite-as-transparent-mesh M3 / w14 (AC-12 / D-7):
|
|
1122
|
+
// the four `forgeax::default-sprite` boot-time pre-warm entries (LDR S1
|
|
1123
|
+
// + LDR S4 + HDR S1 + HDR S4) are gone. Sprite PSO lands lazily through
|
|
1124
|
+
// the generic per-MaterialShader pipeline cache keyed on
|
|
1125
|
+
// `forgeax::sprite` + premultiplied-alpha renderState; SPEC_CONST_TABLE
|
|
1126
|
+
// shrinks from 19 to 15 entries (-4 boot-time PSOs).
|
|
1127
|
+
|
|
1128
|
+
// ── M2-T4: fullscreen-post boot-time pre-warm (tonemap + skybox) ──────────
|
|
1129
|
+
//
|
|
1130
|
+
// Tonemap (LDR S1): fullscreen triangle writes to swap-chain LDR view format
|
|
1131
|
+
// (parameterised — `ldrViewFormat`; see buildSpecConstTable jsdoc + bug-20260615).
|
|
1132
|
+
// Skybox (HDR S1 + S4): fullscreen triangle writes to rgba16float; MSAA variant
|
|
1133
|
+
// has sampleCount=4. Both use empty vertexLayout (fullscreen triangle, no
|
|
1134
|
+
// attributes) and cullMode='none' (forward cull for fullscreen-quad passthrough).
|
|
1135
|
+
//
|
|
1136
|
+
// Shadow-probe / fxaa / bloom 4-stage / SSAO 2-stage are lazy-build — not in
|
|
1137
|
+
// SPEC_CONST_TABLE (R-D4 decision: only entries that are always-present on
|
|
1138
|
+
// every boot).
|
|
1139
|
+
|
|
1140
|
+
// tonemap LDR S1 (writes to runtime-resolved swap-chain LDR view format)
|
|
1141
|
+
{
|
|
1142
|
+
shader: { id: 'forgeax::post::tonemap', passKind: 'post-process', variantSet: undefined },
|
|
1143
|
+
attachments: {
|
|
1144
|
+
colorFormats: [ldrViewFormat],
|
|
1145
|
+
depthFormat: undefined,
|
|
1146
|
+
sampleCount: 1 as const,
|
|
1147
|
+
},
|
|
1148
|
+
geometry: {
|
|
1149
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
1150
|
+
stripIndexFormat: undefined,
|
|
1151
|
+
vertexLayout: {},
|
|
1152
|
+
},
|
|
1153
|
+
renderState: {
|
|
1154
|
+
cullMode: 'none',
|
|
1155
|
+
},
|
|
1156
|
+
},
|
|
1157
|
+
|
|
1158
|
+
// skybox HDR S1 (writes to rgba16float, no depth)
|
|
1159
|
+
{
|
|
1160
|
+
shader: { id: 'forgeax::skybox::cube', passKind: 'skybox', variantSet: undefined },
|
|
1161
|
+
attachments: {
|
|
1162
|
+
colorFormats: [HDR_FORMAT],
|
|
1163
|
+
depthFormat: undefined,
|
|
1164
|
+
sampleCount: 1 as const,
|
|
1165
|
+
},
|
|
1166
|
+
geometry: {
|
|
1167
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
1168
|
+
stripIndexFormat: undefined,
|
|
1169
|
+
vertexLayout: {},
|
|
1170
|
+
},
|
|
1171
|
+
renderState: {
|
|
1172
|
+
cullMode: 'none',
|
|
1173
|
+
},
|
|
1174
|
+
},
|
|
1175
|
+
|
|
1176
|
+
// skybox HDR S4 (MSAA variant)
|
|
1177
|
+
{
|
|
1178
|
+
shader: { id: 'forgeax::skybox::cube', passKind: 'skybox', variantSet: undefined },
|
|
1179
|
+
attachments: {
|
|
1180
|
+
colorFormats: [HDR_FORMAT],
|
|
1181
|
+
depthFormat: undefined,
|
|
1182
|
+
sampleCount: 4 as const,
|
|
1183
|
+
},
|
|
1184
|
+
geometry: {
|
|
1185
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
1186
|
+
stripIndexFormat: undefined,
|
|
1187
|
+
vertexLayout: {},
|
|
1188
|
+
},
|
|
1189
|
+
renderState: {
|
|
1190
|
+
cullMode: 'none',
|
|
1191
|
+
},
|
|
1192
|
+
},
|
|
1193
|
+
];
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
/**
|
|
1197
|
+
* Derive the material-only pre-warm table for a native linear-LDR target.
|
|
1198
|
+
*
|
|
1199
|
+
* The regular SPEC_CONST table targets the swap-chain view, while the
|
|
1200
|
+
* tonemap=none path records geometry directly into the graph-owned
|
|
1201
|
+
* `rgba16float` target. Keep that second attachment matrix derived from the
|
|
1202
|
+
* same material specs so the first frame does not depend on an asynchronous
|
|
1203
|
+
* lazy PSO build.
|
|
1204
|
+
*/
|
|
1205
|
+
export function buildLinearLdrMaterialSpecTable(
|
|
1206
|
+
ldrViewFormat: GPUTextureFormat,
|
|
1207
|
+
): readonly Readonly<PipelineSpec>[] {
|
|
1208
|
+
return buildSpecConstTable(ldrViewFormat)
|
|
1209
|
+
.filter(
|
|
1210
|
+
(spec) =>
|
|
1211
|
+
spec.shader.passKind === 'forward' && spec.attachments.colorFormats[0] === ldrViewFormat,
|
|
1212
|
+
)
|
|
1213
|
+
.map((spec) => ({
|
|
1214
|
+
...spec,
|
|
1215
|
+
attachments: {
|
|
1216
|
+
...spec.attachments,
|
|
1217
|
+
colorFormats: [HDR_FORMAT],
|
|
1218
|
+
},
|
|
1219
|
+
}));
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* Backward-compatible SPEC_CONST_TABLE — the table built with the default
|
|
1224
|
+
* LDR view format (`bgra8unorm-srgb`). Unit tests that exercise the
|
|
1225
|
+
* spec/cache-keying layer in isolation import this directly. Runtime
|
|
1226
|
+
* callers MUST call `buildSpecConstTable(swapChainFormats.view)` instead
|
|
1227
|
+
* so the pre-warmed PSO color format matches the actual RenderPass color
|
|
1228
|
+
* attachment on every backend (bug-20260615 fix-up).
|
|
1229
|
+
*/
|
|
1230
|
+
export const SPEC_CONST_TABLE: readonly Readonly<PipelineSpec>[] =
|
|
1231
|
+
buildSpecConstTable(DEFAULT_LDR_FORMAT);
|