@forgeax/engine-render 0.1.2
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 +1019 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/__tests__/analytic-sky-contract.test.d.ts +2 -0
- package/dist/__tests__/analytic-sky-contract.test.d.ts.map +1 -0
- package/dist/__tests__/analytic-sky-falsify.test.d.ts +2 -0
- package/dist/__tests__/analytic-sky-falsify.test.d.ts.map +1 -0
- package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts +2 -0
- package/dist/__tests__/assets-runtime-handoff.integration.test.d.ts.map +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__/backend-selection.integration.test.d.ts +2 -0
- package/dist/__tests__/backend-selection.integration.test.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__/camera-temporal.test-d.d.ts +2 -0
- package/dist/__tests__/camera-temporal.test-d.d.ts.map +1 -0
- package/dist/__tests__/camera-temporal.test.d.ts +2 -0
- package/dist/__tests__/camera-temporal.test.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__/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__/directional-shadow-probe-atlas-layout.unit.test.d.ts +2 -0
- package/dist/__tests__/directional-shadow-probe-atlas-layout.unit.test.d.ts.map +1 -0
- package/dist/__tests__/environment-inspection.test.d.ts +2 -0
- package/dist/__tests__/environment-inspection.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__/fog-ai-user.fixture.d.ts +2 -0
- package/dist/__tests__/fog-ai-user.fixture.d.ts.map +1 -0
- package/dist/__tests__/fog-custom-render-feature.fixture.d.ts +16 -0
- package/dist/__tests__/fog-custom-render-feature.fixture.d.ts.map +1 -0
- package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts +2 -0
- package/dist/__tests__/fog-custom-render-feature.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fog-inspection.integration.test.d.ts +2 -0
- package/dist/__tests__/fog-inspection.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fog-owner-state.integration.test.d.ts +2 -0
- package/dist/__tests__/fog-owner-state.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts +2 -0
- package/dist/__tests__/fog-pipeline-topology.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fog-public-surface.integration.test.d.ts +2 -0
- package/dist/__tests__/fog-public-surface.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fog-ray-contract.integration.test.d.ts +2 -0
- package/dist/__tests__/fog-ray-contract.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fog-source-absence.integration.test.d.ts +2 -0
- package/dist/__tests__/fog-source-absence.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fog-temporal.integration.test.d.ts +2 -0
- package/dist/__tests__/fog-temporal.integration.test.d.ts.map +1 -0
- package/dist/__tests__/frame-chain.unit.test.d.ts +2 -0
- package/dist/__tests__/frame-chain.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__/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 +12 -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.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-field-type-owner.test-d.d.ts +2 -0
- package/dist/__tests__/gpu-scene-field-type-owner.test-d.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__/hdrp-pipeline.unit.test.d.ts +2 -0
- package/dist/__tests__/hdrp-pipeline.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ibl/ibl-fallback.unit.test.d.ts +2 -0
- package/dist/__tests__/ibl/ibl-fallback.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-derived-error-stop-draw.integration.test.d.ts +2 -0
- package/dist/__tests__/material-derived-error-stop-draw.integration.test.d.ts.map +1 -0
- package/dist/__tests__/material-derived-payload.integration.test.d.ts +2 -0
- package/dist/__tests__/material-derived-payload.integration.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__/materials.unit.test.d.ts +2 -0
- package/dist/__tests__/materials.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-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__/param-schema-projection-census.unit.test.d.ts +2 -0
- package/dist/__tests__/param-schema-projection-census.unit.test.d.ts.map +1 -0
- package/dist/__tests__/persistent-render-scene.unit.test.d.ts +2 -0
- package/dist/__tests__/persistent-render-scene.unit.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts +2 -0
- package/dist/__tests__/pipeline-error-policy-owner.unit.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline-pass-trace.test.d.ts +2 -0
- package/dist/__tests__/pipeline-pass-trace.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline-stage-owner.test-d.d.ts +2 -0
- package/dist/__tests__/pipeline-stage-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/plugin.test.d.ts +2 -0
- package/dist/__tests__/plugin.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-backend-matrix.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-backend-matrix.unit.test.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-recording.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-resolver-recording.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-pipeline-id.test-d.d.ts +2 -0
- package/dist/__tests__/public-pipeline-id.test-d.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-dispatch-membership.unit.test.d.ts +2 -0
- package/dist/__tests__/render-dispatch-membership.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-construction.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-construction.unit.test.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-error-code-owner.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-error-code-owner.test-d.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-buffer-usage-owner.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-gpu-buffer-usage-owner.test-d.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-graph.integration.test.d.ts +2 -0
- package/dist/__tests__/render-feature-graph.integration.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-graphics-staging.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-order.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-order.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-recording.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics-recording.unit.test.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-staging.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-staging.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__/renderer-render-scene-public.test-d.d.ts +2 -0
- package/dist/__tests__/renderer-render-scene-public.test-d.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__/scene-temporal-coverage.unit.test.d.ts +2 -0
- package/dist/__tests__/scene-temporal-coverage.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-kernel-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/sun-snapshot-consumers.test.d.ts +2 -0
- package/dist/__tests__/sun-snapshot-consumers.test.d.ts.map +1 -0
- package/dist/__tests__/surface-backend-kind-owner.test-d.d.ts +2 -0
- package/dist/__tests__/surface-backend-kind-owner.test-d.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__/taa-history-store.unit.test.d.ts +2 -0
- package/dist/__tests__/taa-history-store.unit.test.d.ts.map +1 -0
- package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts +2 -0
- package/dist/__tests__/temporal-frame-transaction.integration.test.d.ts.map +1 -0
- package/dist/__tests__/temporal-inspection.unit.test.d.ts +2 -0
- package/dist/__tests__/temporal-inspection.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-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/assets/__tests__/asset-decoders.unit.test.d.ts +2 -0
- package/dist/assets/__tests__/asset-decoders.unit.test.d.ts.map +1 -0
- package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts +2 -0
- package/dist/assets/__tests__/mipmap-generator.unit.test.d.ts.map +1 -0
- package/dist/assets/__tests__/render-asset-port.unit.test.d.ts +2 -0
- package/dist/assets/__tests__/render-asset-port.unit.test.d.ts.map +1 -0
- package/dist/assets/__tests__/resolve-render-asset.unit.test.d.ts +2 -0
- package/dist/assets/__tests__/resolve-render-asset.unit.test.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 +5 -0
- package/dist/authoring.mjs.map +1 -0
- package/dist/chunk-33UF5SAO.mjs +7397 -0
- package/dist/chunk-33UF5SAO.mjs.map +1 -0
- package/dist/chunk-A5QCJSNL.mjs +29913 -0
- package/dist/chunk-A5QCJSNL.mjs.map +1 -0
- package/dist/chunk-JMSB7AR4.mjs +3 -0
- package/dist/chunk-JMSB7AR4.mjs.map +1 -0
- package/dist/chunk-LXNGO6AO.mjs +569 -0
- package/dist/chunk-LXNGO6AO.mjs.map +1 -0
- package/dist/chunk-QRXPSX4X.mjs +659 -0
- package/dist/chunk-QRXPSX4X.mjs.map +1 -0
- package/dist/chunk-YAKEQPWO.mjs +1439 -0
- package/dist/chunk-YAKEQPWO.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__/atmosphere-red.test.d.ts +2 -0
- package/dist/components/__tests__/atmosphere-red.test.d.ts.map +1 -0
- package/dist/components/__tests__/atmosphere.test.d.ts +2 -0
- package/dist/components/__tests__/atmosphere.test.d.ts.map +1 -0
- package/dist/components/__tests__/fog.test-d.d.ts +2 -0
- package/dist/components/__tests__/fog.test-d.d.ts.map +1 -0
- package/dist/components/__tests__/fog.test.d.ts +2 -0
- package/dist/components/__tests__/fog.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/atmosphere.d.ts +18 -0
- package/dist/components/atmosphere.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/environment.d.ts +116 -0
- package/dist/components/environment.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 +22 -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/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/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/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 +75 -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 +37 -0
- package/dist/components/sprite-playback-mode.d.ts.map +1 -0
- package/dist/components/sprite-region-override.d.ts +47 -0
- package/dist/components/sprite-region-override.d.ts.map +1 -0
- package/dist/components/tile-layer.d.ts +101 -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 +2 -0
- package/dist/construct-renderer.d.ts.map +1 -0
- package/dist/construct-renderer.mjs +6 -0
- package/dist/construct-renderer.mjs.map +1 -0
- package/dist/debug-draw-glue.d.ts +56 -0
- package/dist/debug-draw-glue.d.ts.map +1 -0
- package/dist/deferred-lighting.d.ts +13 -0
- package/dist/deferred-lighting.d.ts.map +1 -0
- package/dist/dynamic-texture-store.d.ts +42 -0
- package/dist/dynamic-texture-store.d.ts.map +1 -0
- package/dist/engine-metrics.d.ts +23 -0
- package/dist/engine-metrics.d.ts.map +1 -0
- package/dist/environment/__tests__/failure-injection.test.d.ts +2 -0
- package/dist/environment/__tests__/failure-injection.test.d.ts.map +1 -0
- package/dist/environment/__tests__/generation-red.test.d.ts +2 -0
- package/dist/environment/__tests__/generation-red.test.d.ts.map +1 -0
- package/dist/environment/__tests__/generation.test.d.ts +2 -0
- package/dist/environment/__tests__/generation.test.d.ts.map +1 -0
- package/dist/environment/__tests__/graph-transaction.test.d.ts +2 -0
- package/dist/environment/__tests__/graph-transaction.test.d.ts.map +1 -0
- package/dist/environment/__tests__/inspection-red.test.d.ts +2 -0
- package/dist/environment/__tests__/inspection-red.test.d.ts.map +1 -0
- package/dist/environment/__tests__/lifecycle-evidence.test.d.ts +2 -0
- package/dist/environment/__tests__/lifecycle-evidence.test.d.ts.map +1 -0
- package/dist/environment/__tests__/pipeline-topology.test.d.ts +2 -0
- package/dist/environment/__tests__/pipeline-topology.test.d.ts.map +1 -0
- package/dist/environment/__tests__/readiness.test.d.ts +2 -0
- package/dist/environment/__tests__/readiness.test.d.ts.map +1 -0
- package/dist/environment/__tests__/recovery.test.d.ts +2 -0
- package/dist/environment/__tests__/recovery.test.d.ts.map +1 -0
- package/dist/environment/__tests__/resize-dispose.test.d.ts +2 -0
- package/dist/environment/__tests__/resize-dispose.test.d.ts.map +1 -0
- package/dist/environment/__tests__/signature-red.test.d.ts +2 -0
- package/dist/environment/__tests__/signature-red.test.d.ts.map +1 -0
- package/dist/environment/__tests__/signature.test.d.ts +2 -0
- package/dist/environment/__tests__/signature.test.d.ts.map +1 -0
- package/dist/environment/descriptors.d.ts +2 -0
- package/dist/environment/descriptors.d.ts.map +1 -0
- package/dist/environment/extracted-environment.d.ts +53 -0
- package/dist/environment/extracted-environment.d.ts.map +1 -0
- package/dist/environment/generation.d.ts +62 -0
- package/dist/environment/generation.d.ts.map +1 -0
- package/dist/environment/gpu-bundle.d.ts +23 -0
- package/dist/environment/gpu-bundle.d.ts.map +1 -0
- package/dist/environment/graph.d.ts +108 -0
- package/dist/environment/graph.d.ts.map +1 -0
- package/dist/environment/inspection.d.ts +48 -0
- package/dist/environment/inspection.d.ts.map +1 -0
- package/dist/environment/lifecycle.d.ts +22 -0
- package/dist/environment/lifecycle.d.ts.map +1 -0
- package/dist/environment/readiness.d.ts +29 -0
- package/dist/environment/readiness.d.ts.map +1 -0
- package/dist/environment/signature.d.ts +70 -0
- package/dist/environment/signature.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 +78 -0
- package/dist/errors/recover.d.ts.map +1 -0
- package/dist/errors/render.d.ts +633 -0
- package/dist/errors/render.d.ts.map +1 -0
- package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts +2 -0
- package/dist/extract/__tests__/directional-csm-domain.unit.test.d.ts.map +1 -0
- package/dist/extract/__tests__/environment-source.test.d.ts +2 -0
- package/dist/extract/__tests__/environment-source.test.d.ts.map +1 -0
- package/dist/extract/__tests__/schema-readers.unit.test.d.ts +2 -0
- package/dist/extract/__tests__/schema-readers.unit.test.d.ts.map +1 -0
- package/dist/extract/directional-csm.d.ts +129 -0
- package/dist/extract/directional-csm.d.ts.map +1 -0
- package/dist/extract/index.d.ts +5 -0
- package/dist/extract/index.d.ts.map +1 -0
- package/dist/extract/material-interface.d.ts +56 -0
- package/dist/extract/material-interface.d.ts.map +1 -0
- package/dist/extract/schema-readers.d.ts +20 -0
- package/dist/extract/schema-readers.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/graph-contribution.d.ts +64 -0
- package/dist/features/graph-contribution.d.ts.map +1 -0
- package/dist/features/host.d.ts +100 -0
- package/dist/features/host.d.ts.map +1 -0
- package/dist/features/index.d.ts +21 -0
- package/dist/features/index.d.ts.map +1 -0
- package/dist/features/morph/index.d.ts +3 -0
- package/dist/features/morph/index.d.ts.map +1 -0
- package/dist/features/morph/morph-bounds.d.ts +42 -0
- package/dist/features/morph/morph-bounds.d.ts.map +1 -0
- package/dist/features/morph/morph-feature.d.ts +45 -0
- package/dist/features/morph/morph-feature.d.ts.map +1 -0
- package/dist/features/prepared-gpu-work.d.ts +113 -0
- package/dist/features/prepared-gpu-work.d.ts.map +1 -0
- package/dist/features/prepared-graphics-store.d.ts +65 -0
- package/dist/features/prepared-graphics-store.d.ts.map +1 -0
- package/dist/features/prepared-graphics.d.ts +225 -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 +15 -0
- package/dist/features/render-graph-contribution.d.ts.map +1 -0
- package/dist/features/render-graph-raster.d.ts +34 -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/scene-temporal.d.ts +45 -0
- package/dist/features/scene-temporal.d.ts.map +1 -0
- package/dist/features/taa-resolve.d.ts +21 -0
- package/dist/features/taa-resolve.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 +247 -0
- package/dist/features/types.d.ts.map +1 -0
- package/dist/frame-chain.d.ts +14 -0
- package/dist/frame-chain.d.ts.map +1 -0
- package/dist/fullscreen-post-process-pass.d.ts +178 -0
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -0
- package/dist/glyph-text-layout-system.d.ts +18 -0
- package/dist/glyph-text-layout-system.d.ts.map +1 -0
- package/dist/gpu-driven/batch-topology.d.ts +124 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +150 -0
- package/dist/gpu-driven/production-raster.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +141 -0
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -0
- package/dist/gpu-driven/view-reference.d.ts +15 -0
- package/dist/gpu-driven/view-reference.d.ts.map +1 -0
- package/dist/gpu-resource-store.d.ts +294 -0
- package/dist/gpu-resource-store.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 +171 -0
- package/dist/gpu-scene-schema.d.ts.map +1 -0
- package/dist/gpu-scene.d.ts +81 -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 +213 -0
- package/dist/hdrp-buffers.d.ts.map +1 -0
- package/dist/hdrp-cluster-membership.d.ts +2 -0
- package/dist/hdrp-cluster-membership.d.ts.map +1 -0
- package/dist/hdrp-pipeline.d.ts +36 -0
- package/dist/hdrp-pipeline.d.ts.map +1 -0
- package/dist/ibl/IblPipelineCache.d.ts +274 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -0
- package/dist/ibl/cubemap-projection.d.ts +23 -0
- package/dist/ibl/cubemap-projection.d.ts.map +1 -0
- package/dist/ibl/face-uniforms.d.ts +65 -0
- package/dist/ibl/face-uniforms.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 +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +5 -0
- package/dist/index.mjs.map +1 -0
- package/dist/instance-buffer-cache.d.ts +59 -0
- package/dist/instance-buffer-cache.d.ts.map +1 -0
- package/dist/internal.d.ts +74 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.mjs +45 -0
- package/dist/internal.mjs.map +1 -0
- package/dist/lifecycle.d.ts +28 -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 +50 -0
- package/dist/materials.d.ts.map +1 -0
- package/dist/mesh-material-bindings.d.ts +44 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -0
- package/dist/mesh-update-errors.d.ts +71 -0
- package/dist/mesh-update-errors.d.ts.map +1 -0
- package/dist/mipmap-generator.d.ts +39 -0
- package/dist/mipmap-generator.d.ts.map +1 -0
- package/dist/param-schema-projection-census.d.ts +18 -0
- package/dist/param-schema-projection-census.d.ts.map +1 -0
- package/dist/pbr-pipeline.d.ts +253 -0
- package/dist/pbr-pipeline.d.ts.map +1 -0
- package/dist/persistent-render-scene.d.ts +158 -0
- package/dist/persistent-render-scene.d.ts.map +1 -0
- package/dist/pipeline/index.d.ts +11 -0
- package/dist/pipeline/index.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-errors.d.ts +110 -0
- package/dist/pipeline-errors.d.ts.map +1 -0
- package/dist/pipeline-spec.d.ts +506 -0
- package/dist/pipeline-spec.d.ts.map +1 -0
- package/dist/plugin.d.ts +17 -0
- package/dist/plugin.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/__tests__/schema-readers.unit.test.d.ts +2 -0
- package/dist/prepare/__tests__/schema-readers.unit.test.d.ts.map +1 -0
- package/dist/prepare/index.d.ts +4 -0
- package/dist/prepare/index.d.ts.map +1 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts +62 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -0
- package/dist/prepare/schema-readers.d.ts +11 -0
- package/dist/prepare/schema-readers.d.ts.map +1 -0
- package/dist/record/__tests__/environment-record.test.d.ts +2 -0
- package/dist/record/__tests__/environment-record.test.d.ts.map +1 -0
- package/dist/record/__tests__/frame-targets.unit.test.d.ts +2 -0
- package/dist/record/__tests__/frame-targets.unit.test.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__/membership-timing.unit.test.d.ts +2 -0
- package/dist/record/__tests__/membership-timing.unit.test.d.ts.map +1 -0
- package/dist/record/__tests__/render-submission.integration.test.d.ts +2 -0
- package/dist/record/__tests__/render-submission.integration.test.d.ts.map +1 -0
- package/dist/record/__tests__/render-submission.perf.test.d.ts +2 -0
- package/dist/record/__tests__/render-submission.perf.test.d.ts.map +1 -0
- package/dist/record/__tests__/shadow-submit-mode.unit.test.d.ts +2 -0
- package/dist/record/__tests__/shadow-submit-mode.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/__tests__/view-ubo-layout.unit.test.d.ts +2 -0
- package/dist/record/__tests__/view-ubo-layout.unit.test.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +187 -0
- package/dist/record/frame-lighting.d.ts.map +1 -0
- package/dist/record/frame-observation.d.ts +38 -0
- package/dist/record/frame-observation.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 +53 -0
- package/dist/record/frame-targets.d.ts.map +1 -0
- package/dist/record/frame.d.ts +59 -0
- package/dist/record/frame.d.ts.map +1 -0
- package/dist/record/helpers.d.ts +101 -0
- package/dist/record/helpers.d.ts.map +1 -0
- package/dist/record/index.d.ts +15 -0
- package/dist/record/index.d.ts.map +1 -0
- package/dist/record/main-pass-geometry.d.ts +20 -0
- package/dist/record/main-pass-geometry.d.ts.map +1 -0
- package/dist/record/main-pass-material.d.ts +173 -0
- package/dist/record/main-pass-material.d.ts.map +1 -0
- package/dist/record/main-pass-skin.d.ts +46 -0
- package/dist/record/main-pass-skin.d.ts.map +1 -0
- package/dist/record/main-pass-sprite-draws.d.ts +18 -0
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -0
- package/dist/record/main-pass-sprite.d.ts +69 -0
- package/dist/record/main-pass-sprite.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/material-payload.d.ts +43 -0
- package/dist/record/material-payload.d.ts.map +1 -0
- package/dist/record/material-slot-plan.d.ts +26 -0
- package/dist/record/material-slot-plan.d.ts.map +1 -0
- package/dist/record/membership-timing.d.ts +232 -0
- package/dist/record/membership-timing.d.ts.map +1 -0
- package/dist/record/mesh-ssbo.d.ts +173 -0
- package/dist/record/mesh-ssbo.d.ts.map +1 -0
- package/dist/record/shadow-caster-uniform.d.ts +8 -0
- package/dist/record/shadow-caster-uniform.d.ts.map +1 -0
- package/dist/record/shadow-pass.d.ts +125 -0
- package/dist/record/shadow-pass.d.ts.map +1 -0
- package/dist/record/shadow-submit-mode.d.ts +66 -0
- package/dist/record/shadow-submit-mode.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 +13 -0
- package/dist/record/typed-frame-graph.d.ts.map +1 -0
- package/dist/record/view-ubo.d.ts +39 -0
- package/dist/record/view-ubo.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-dispatch-membership.d.ts +47 -0
- package/dist/render-dispatch-membership.d.ts.map +1 -0
- package/dist/render-graph-primitives.d.ts +424 -0
- package/dist/render-graph-primitives.d.ts.map +1 -0
- package/dist/render-pipeline-context.d.ts +289 -0
- package/dist/render-pipeline-context.d.ts.map +1 -0
- package/dist/render-pipeline-target.d.ts +16 -0
- package/dist/render-pipeline-target.d.ts.map +1 -0
- package/dist/render-pipeline.d.ts +149 -0
- package/dist/render-pipeline.d.ts.map +1 -0
- package/dist/render-scene-projection.d.ts +174 -0
- package/dist/render-scene-projection.d.ts.map +1 -0
- package/dist/render-system-extract.d.ts +1096 -0
- package/dist/render-system-extract.d.ts.map +1 -0
- package/dist/render-system-fold.d.ts +266 -0
- package/dist/render-system-fold.d.ts.map +1 -0
- package/dist/render-system.d.ts +814 -0
- package/dist/render-system.d.ts.map +1 -0
- package/dist/renderer/asset-service.d.ts +10 -0
- package/dist/renderer/asset-service.d.ts.map +1 -0
- package/dist/renderer/backend-selection.d.ts +26 -0
- package/dist/renderer/backend-selection.d.ts.map +1 -0
- package/dist/renderer/environment-classify.d.ts +6 -0
- package/dist/renderer/environment-classify.d.ts.map +1 -0
- package/dist/renderer/environment-error.d.ts +13 -0
- package/dist/renderer/environment-error.d.ts.map +1 -0
- package/dist/renderer/material/assembly.d.ts +22 -0
- package/dist/renderer/material/assembly.d.ts.map +1 -0
- package/dist/renderer/material/pipeline-projection.d.ts +91 -0
- package/dist/renderer/material/pipeline-projection.d.ts.map +1 -0
- package/dist/renderer/renderer-factory.d.ts +283 -0
- package/dist/renderer/renderer-factory.d.ts.map +1 -0
- package/dist/renderer.d.ts +771 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts +33 -0
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -0
- package/dist/scene-utils/collect-subtree.d.ts +11 -0
- package/dist/scene-utils/collect-subtree.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 +31 -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/ssao-data.d.ts +34 -0
- package/dist/ssao-data.d.ts.map +1 -0
- package/dist/surface-format.d.ts +10 -0
- package/dist/surface-format.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 +51 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -0
- package/dist/systems/transparent-sort-config.d.ts +91 -0
- package/dist/systems/transparent-sort-config.d.ts.map +1 -0
- package/dist/taa-history-store.d.ts +88 -0
- package/dist/taa-history-store.d.ts.map +1 -0
- package/dist/temporal-coverage.d.ts +35 -0
- package/dist/temporal-coverage.d.ts.map +1 -0
- package/dist/temporal-frame-transaction.d.ts +92 -0
- package/dist/temporal-frame-transaction.d.ts.map +1 -0
- package/dist/temporal-inspection.d.ts +57 -0
- package/dist/temporal-inspection.d.ts.map +1 -0
- package/dist/temporal-view.d.ts +43 -0
- package/dist/temporal-view.d.ts.map +1 -0
- package/dist/tilemap/resolve-tileset-runtime.d.ts +23 -0
- package/dist/tilemap/resolve-tileset-runtime.d.ts.map +1 -0
- package/dist/tilemap-chunk-extract-system.d.ts +142 -0
- package/dist/tilemap-chunk-extract-system.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +59 -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/dist/urp-pipeline.d.ts +4 -0
- package/dist/urp-pipeline.d.ts.map +1 -0
- package/package.json +94 -0
- package/src/__tests__/analytic-sky-contract.test.ts +27 -0
- package/src/__tests__/analytic-sky-falsify-carriers.mjs +43 -0
- package/src/__tests__/analytic-sky-falsify.test.ts +94 -0
- package/src/__tests__/assets-runtime-handoff.integration.test.ts +36 -0
- package/src/__tests__/authoring-path.unit.test.ts +14 -0
- package/src/__tests__/backend-selection-rhi-capture.test-d.ts +21 -0
- package/src/__tests__/backend-selection.integration.test.ts +11 -0
- package/src/__tests__/callback-inference.test-d.ts +5 -0
- package/src/__tests__/camera-temporal.test-d.ts +8 -0
- package/src/__tests__/camera-temporal.test.ts +188 -0
- package/src/__tests__/cluster-binner.test.ts +272 -0
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +17 -0
- package/src/__tests__/construct-renderer-identity.unit.test.ts +10 -0
- package/src/__tests__/direct-extract-consumer-contract.test-d.ts +34 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +71 -0
- package/src/__tests__/directional-shadow-probe-atlas-layout.unit.test.ts +18 -0
- package/src/__tests__/environment-inspection.test.ts +45 -0
- package/src/__tests__/factory-contract.integration.test.ts +331 -0
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +18 -0
- package/src/__tests__/fog-ai-user.fixture.ts +350 -0
- package/src/__tests__/fog-custom-render-feature.fixture.ts +33 -0
- package/src/__tests__/fog-custom-render-feature.integration.test.ts +76 -0
- package/src/__tests__/fog-inspection.integration.test.ts +127 -0
- package/src/__tests__/fog-owner-state.integration.test.ts +112 -0
- package/src/__tests__/fog-pipeline-topology.integration.test.ts +93 -0
- package/src/__tests__/fog-public-surface.integration.test.ts +60 -0
- package/src/__tests__/fog-ray-contract.integration.test.ts +73 -0
- package/src/__tests__/fog-source-absence.integration.test.ts +51 -0
- package/src/__tests__/fog-temporal.integration.test.ts +115 -0
- package/src/__tests__/frame-chain.unit.test.ts +26 -0
- package/src/__tests__/frame-observation.contract.test.ts +103 -0
- package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +172 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +347 -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 +609 -0
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +90 -0
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +192 -0
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +128 -0
- package/src/__tests__/gpu-driven-view.browser.test.ts +19 -0
- package/src/__tests__/gpu-driven-view.dawn.test.ts +17 -0
- package/src/__tests__/gpu-driven-view.unit.test.ts +455 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +59 -0
- package/src/__tests__/gpu-scene-field-type-owner.test-d.ts +27 -0
- package/src/__tests__/gpu-scene-render-graph-gpu.ts +309 -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 +209 -0
- package/src/__tests__/gpu-scene.unit.test.ts +161 -0
- package/src/__tests__/hdrp-pipeline.unit.test.ts +100 -0
- package/src/__tests__/ibl/ibl-fallback.unit.test.ts +23 -0
- package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +124 -0
- package/src/__tests__/injection-kind-owner.test-d.ts +14 -0
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +719 -0
- package/src/__tests__/light-buffer-layout.unit.test.ts +85 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +24 -0
- package/src/__tests__/material-cooked-projection.unit.test.ts +177 -0
- package/src/__tests__/material-derived-error-stop-draw.integration.test.ts +69 -0
- package/src/__tests__/material-derived-payload.integration.test.ts +164 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +58 -0
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +113 -0
- package/src/__tests__/material-stride-surface.unit.test.ts +32 -0
- package/src/__tests__/materials.unit.test.ts +25 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +107 -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 +166 -0
- package/src/__tests__/morph-feature-gpu-work.integration.test.ts +78 -0
- package/src/__tests__/morph-visual-evidence.integration.test.ts +66 -0
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +14 -0
- package/src/__tests__/param-schema-projection-census.unit.test.ts +40 -0
- package/src/__tests__/persistent-render-scene.unit.test.ts +1311 -0
- package/src/__tests__/pipeline-error-policy-owner.unit.test.ts +167 -0
- package/src/__tests__/pipeline-pass-trace.test.ts +92 -0
- package/src/__tests__/pipeline-stage-owner.test-d.ts +13 -0
- package/src/__tests__/plugin.test.ts +25 -0
- package/src/__tests__/post-process-error-policy-owner.unit.test.ts +208 -0
- package/src/__tests__/prepared-buffer-kind-owner.test-d.ts +29 -0
- package/src/__tests__/prepared-graphics-backend-matrix.unit.test.ts +129 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +140 -0
- package/src/__tests__/prepared-graphics-generation.unit.test.ts +175 -0
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +206 -0
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +29 -0
- package/src/__tests__/prepared-graphics-resolver-recording.unit.test.ts +180 -0
- package/src/__tests__/prepared-graphics-resolver.unit.test.ts +287 -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 +70 -0
- package/src/__tests__/profiler-phase-token.test.ts +84 -0
- package/src/__tests__/public-pipeline-id.test-d.ts +6 -0
- package/src/__tests__/public-surface.test-d.ts +32 -0
- package/src/__tests__/recover-error-policy-owner.unit.test.ts +127 -0
- package/src/__tests__/render-dispatch-membership.unit.test.ts +117 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +115 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +234 -0
- package/src/__tests__/render-error-exhaustive.test-d.ts +84 -0
- package/src/__tests__/render-feature-assembly.test-d.ts +51 -0
- package/src/__tests__/render-feature-construction.unit.test.ts +124 -0
- package/src/__tests__/render-feature-context.test-d.ts +81 -0
- package/src/__tests__/render-feature-contract.test-d.ts +58 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +151 -0
- package/src/__tests__/render-feature-docs.unit.test.ts +88 -0
- package/src/__tests__/render-feature-error-code-owner.test-d.ts +27 -0
- package/src/__tests__/render-feature-errors.unit.test.ts +47 -0
- package/src/__tests__/render-feature-gpu-buffer-usage-owner.test-d.ts +46 -0
- package/src/__tests__/render-feature-gpu-work.integration.test.ts +377 -0
- package/src/__tests__/render-feature-graph.integration.test.ts +205 -0
- package/src/__tests__/render-feature-graphics-staging.unit.test.ts +200 -0
- package/src/__tests__/render-feature-order.unit.test.ts +66 -0
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +101 -0
- package/src/__tests__/render-feature-prepared-errors.test-d.ts +82 -0
- package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +141 -0
- package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +122 -0
- package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +59 -0
- package/src/__tests__/render-feature-prepared-graphics-recording.unit.test.ts +107 -0
- package/src/__tests__/render-feature-prepared-graphics.test-d.ts +96 -0
- package/src/__tests__/render-feature-prepared-graphics.unit.test.ts +121 -0
- package/src/__tests__/render-feature-public-surface.test-d.ts +75 -0
- package/src/__tests__/render-feature-retry.unit.test.ts +128 -0
- package/src/__tests__/render-feature-scheduling.unit.test.ts +122 -0
- package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +146 -0
- package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +236 -0
- package/src/__tests__/render-feature-staging.unit.test.ts +94 -0
- package/src/__tests__/render-feature-visibility-context.test-d.ts +38 -0
- package/src/__tests__/render-feature-visibility-context.unit.test.ts +38 -0
- package/src/__tests__/render-feature-zero-work.unit.test.ts +82 -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 +206 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +125 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +10 -0
- package/src/__tests__/renderer-render-scene-public.test-d.ts +27 -0
- package/src/__tests__/rhi-backend-package-boundary.unit.test.ts +11 -0
- package/src/__tests__/scene-temporal-coverage.unit.test.ts +259 -0
- package/src/__tests__/scriptable-pack-consumer.test-d.ts +14 -0
- package/src/__tests__/shader-stage-surface.unit.test.ts +38 -0
- package/src/__tests__/ssao-kernel-surface.unit.test.ts +15 -0
- package/src/__tests__/sun-snapshot-consumers.test.ts +35 -0
- package/src/__tests__/surface-backend-kind-owner.test-d.ts +42 -0
- package/src/__tests__/surface-configuration.unit.test.ts +92 -0
- package/src/__tests__/taa-history-store.unit.test.ts +196 -0
- package/src/__tests__/temporal-frame-transaction.integration.test.ts +537 -0
- package/src/__tests__/temporal-inspection.unit.test.ts +138 -0
- package/src/__tests__/texture-usage-surface.unit.test.ts +61 -0
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +389 -0
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +52 -0
- package/src/__tests__/urp-pipeline.unit.test.ts +14 -0
- package/src/__tests__/vertex-color-pipeline.unit.test.ts +124 -0
- package/src/__tests__/vertex-layout-consumer.unit.test.ts +25 -0
- package/src/__tests__/visibility-diagnostics.integration.test.ts +66 -0
- package/src/__tests__/visibility-extract.integration.test.ts +89 -0
- package/src/__tests__/visibility-extract.perf.test.ts +96 -0
- package/src/__tests__/visibility-feature-dedup.integration.test.ts +57 -0
- package/src/__tests__/visibility-hidden-report.unit.test.ts +37 -0
- package/src/__tests__/visibility-instances.integration.test.ts +50 -0
- package/src/__tests__/visibility-multi-world.integration.test.ts +54 -0
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +191 -0
- package/src/__tests__/visibility-producer-matrix.unit.test.ts +96 -0
- package/src/__tests__/visibility-public-surface.test-d.ts +26 -0
- package/src/__tests__/visibility-resolver.unit.test.ts +84 -0
- package/src/__tests__/visibility-snapshot-contract.unit.test.ts +59 -0
- package/src/__tests__/vocabulary.unit.test.ts +21 -0
- package/src/assets/__tests__/asset-decoders.unit.test.ts +92 -0
- package/src/assets/__tests__/mipmap-generator.unit.test.ts +52 -0
- package/src/assets/__tests__/render-asset-port.unit.test.ts +54 -0
- package/src/assets/__tests__/resolve-render-asset.unit.test.ts +47 -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 +24 -0
- package/src/cluster-binner.ts +700 -0
- package/src/components/__tests__/atmosphere-red.test.ts +51 -0
- package/src/components/__tests__/atmosphere.test.ts +79 -0
- package/src/components/__tests__/fog.test-d.ts +49 -0
- package/src/components/__tests__/fog.test.ts +60 -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/atmosphere.ts +64 -0
- package/src/components/camera.ts +512 -0
- package/src/components/directional-light.ts +120 -0
- package/src/components/environment.ts +206 -0
- package/src/components/glyph-text.ts +63 -0
- package/src/components/index.ts +49 -0
- package/src/components/instances.ts +207 -0
- package/src/components/layer.ts +69 -0
- package/src/components/light-helpers.ts +188 -0
- package/src/components/mesh-filter.ts +59 -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/post-process-params.ts +35 -0
- package/src/components/scene-instance.ts +193 -0
- package/src/components/sort-key.ts +75 -0
- package/src/components/spot-light.ts +124 -0
- package/src/components/sprite-animation.ts +169 -0
- package/src/components/sprite-instances.ts +179 -0
- package/src/components/sprite-playback-mode.ts +73 -0
- package/src/components/sprite-region-override.ts +106 -0
- package/src/components/tile-layer.ts +161 -0
- package/src/components/tilemap.ts +48 -0
- package/src/components/visibility.ts +53 -0
- package/src/construct-renderer.ts +4 -0
- package/src/debug-draw-glue.ts +169 -0
- package/src/deferred-lighting.ts +92 -0
- package/src/dynamic-texture-store.ts +111 -0
- package/src/engine-metrics.ts +89 -0
- package/src/environment/README.md +76 -0
- package/src/environment/__tests__/failure-injection.test.ts +50 -0
- package/src/environment/__tests__/generation-red.test.ts +64 -0
- package/src/environment/__tests__/generation.test.ts +37 -0
- package/src/environment/__tests__/graph-transaction.test.ts +85 -0
- package/src/environment/__tests__/inspection-red.test.ts +53 -0
- package/src/environment/__tests__/lifecycle-evidence.test.ts +40 -0
- package/src/environment/__tests__/pipeline-topology.test.ts +33 -0
- package/src/environment/__tests__/readiness.test.ts +42 -0
- package/src/environment/__tests__/recovery.test.ts +62 -0
- package/src/environment/__tests__/resize-dispose.test.ts +30 -0
- package/src/environment/__tests__/signature-red.test.ts +45 -0
- package/src/environment/__tests__/signature.test.ts +60 -0
- package/src/environment/descriptors.ts +7 -0
- package/src/environment/extracted-environment.ts +239 -0
- package/src/environment/generation.ts +158 -0
- package/src/environment/gpu-bundle.ts +144 -0
- package/src/environment/graph.ts +588 -0
- package/src/environment/inspection.ts +107 -0
- package/src/environment/lifecycle.ts +124 -0
- package/src/environment/readiness.ts +76 -0
- package/src/environment/signature.ts +185 -0
- package/src/errors/ecs-validation.ts +16 -0
- package/src/errors/index.ts +3 -0
- package/src/errors/recover.ts +119 -0
- package/src/errors/render.ts +1244 -0
- package/src/extract/__tests__/directional-csm-domain.unit.test.ts +391 -0
- package/src/extract/__tests__/environment-source.test.ts +105 -0
- package/src/extract/__tests__/schema-readers.unit.test.ts +16 -0
- package/src/extract/directional-csm.ts +959 -0
- package/src/extract/index.ts +10 -0
- package/src/extract/material-interface.ts +604 -0
- package/src/extract/schema-readers.ts +27 -0
- package/src/extract/visibility.ts +120 -0
- package/src/features/graph-contribution.ts +577 -0
- package/src/features/host.ts +1097 -0
- package/src/features/index.ts +100 -0
- package/src/features/morph/index.ts +24 -0
- package/src/features/morph/morph-bounds.ts +123 -0
- package/src/features/morph/morph-feature.ts +287 -0
- package/src/features/prepared-gpu-work.ts +902 -0
- package/src/features/prepared-graphics-store.ts +435 -0
- package/src/features/prepared-graphics.ts +479 -0
- package/src/features/render-graph-compute.ts +60 -0
- package/src/features/render-graph-contribution.ts +95 -0
- package/src/features/render-graph-raster.ts +308 -0
- package/src/features/render-graph-resources.ts +36 -0
- package/src/features/scene-temporal.ts +274 -0
- package/src/features/taa-resolve.ts +244 -0
- package/src/features/targets.ts +83 -0
- package/src/features/types.ts +291 -0
- package/src/frame-chain.ts +21 -0
- package/src/fullscreen-post-process-pass.ts +406 -0
- package/src/glyph-text-layout-system.ts +447 -0
- package/src/gpu-driven/batch-topology.ts +423 -0
- package/src/gpu-driven/production-raster.ts +1705 -0
- package/src/gpu-driven/view-gpu.ts +849 -0
- package/src/gpu-driven/view-reference.ts +110 -0
- package/src/gpu-resource-store.ts +1921 -0
- package/src/gpu-resource.ts +159 -0
- package/src/gpu-scene-schema.ts +224 -0
- package/src/gpu-scene.ts +855 -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 +689 -0
- package/src/hdrp-cluster-membership.ts +70 -0
- package/src/hdrp-pipeline.ts +525 -0
- package/src/ibl/IblPipelineCache.ts +1246 -0
- package/src/ibl/cubemap-projection.ts +60 -0
- package/src/ibl/face-uniforms.ts +150 -0
- package/src/ibl/skylight-bind-group.ts +513 -0
- package/src/index.ts +271 -0
- package/src/instance-buffer-cache.ts +123 -0
- package/src/internal.ts +88 -0
- package/src/lifecycle.ts +123 -0
- package/src/light-buffer-layout.ts +346 -0
- package/src/materials.ts +236 -0
- package/src/mesh-material-bindings.ts +104 -0
- package/src/mesh-update-errors.ts +113 -0
- package/src/mipmap-generator.ts +244 -0
- package/src/param-schema-projection-census.ts +73 -0
- package/src/pbr-pipeline.ts +749 -0
- package/src/persistent-render-scene.ts +1752 -0
- package/src/pipeline/index.ts +40 -0
- package/src/pipeline-builder.ts +386 -0
- package/src/pipeline-errors.ts +172 -0
- package/src/pipeline-spec.ts +1768 -0
- package/src/plugin.ts +137 -0
- package/src/post-process-errors.ts +304 -0
- package/src/prepare/__tests__/schema-readers.unit.test.ts +16 -0
- package/src/prepare/index.ts +8 -0
- package/src/prepare/prepared-graphics-resolver.ts +455 -0
- package/src/prepare/schema-readers.ts +20 -0
- package/src/record/__tests__/environment-record.test.ts +35 -0
- package/src/record/__tests__/frame-targets.unit.test.ts +54 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +41 -0
- package/src/record/__tests__/material-slot-plan.unit.test.ts +76 -0
- package/src/record/__tests__/membership-timing.unit.test.ts +524 -0
- package/src/record/__tests__/render-submission.integration.test.ts +76 -0
- package/src/record/__tests__/render-submission.perf.test.ts +141 -0
- package/src/record/__tests__/shadow-submit-mode.unit.test.ts +88 -0
- package/src/record/__tests__/video-texture-view.unit.test.ts +90 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +101 -0
- package/src/record/frame-lighting.ts +1183 -0
- package/src/record/frame-observation.ts +122 -0
- package/src/record/frame-snapshot.ts +515 -0
- package/src/record/frame-targets.ts +372 -0
- package/src/record/frame.ts +1874 -0
- package/src/record/helpers.ts +289 -0
- package/src/record/index.ts +15 -0
- package/src/record/main-pass-geometry.ts +1014 -0
- package/src/record/main-pass-material.ts +716 -0
- package/src/record/main-pass-skin.ts +51 -0
- package/src/record/main-pass-sprite-draws.ts +1056 -0
- package/src/record/main-pass-sprite.ts +166 -0
- package/src/record/main-pass.ts +588 -0
- package/src/record/material-payload.ts +292 -0
- package/src/record/material-slot-plan.ts +68 -0
- package/src/record/membership-timing.ts +1012 -0
- package/src/record/mesh-ssbo.ts +406 -0
- package/src/record/shadow-caster-uniform.ts +37 -0
- package/src/record/shadow-pass.ts +2387 -0
- package/src/record/shadow-submit-mode.ts +277 -0
- package/src/record/skybox-post-pass.ts +594 -0
- package/src/record/typed-frame-graph.ts +499 -0
- package/src/record/view-ubo.ts +206 -0
- package/src/render-data.ts +385 -0
- package/src/render-dispatch-membership.ts +155 -0
- package/src/render-graph-primitives.ts +1586 -0
- package/src/render-pipeline-context.ts +332 -0
- package/src/render-pipeline-target.ts +96 -0
- package/src/render-pipeline.ts +343 -0
- package/src/render-scene-projection.ts +1738 -0
- package/src/render-system-extract.ts +5203 -0
- package/src/render-system-fold.ts +531 -0
- package/src/render-system.ts +3258 -0
- package/src/renderer/asset-service.ts +32 -0
- package/src/renderer/backend-selection.ts +121 -0
- package/src/renderer/environment-classify.ts +30 -0
- package/src/renderer/environment-error.ts +19 -0
- package/src/renderer/material/assembly.ts +53 -0
- package/src/renderer/material/pipeline-projection.ts +140 -0
- package/src/renderer/renderer-factory.ts +9062 -0
- package/src/renderer.ts +940 -0
- package/src/scene-instances/post-spawn-resolve-joints.ts +168 -0
- package/src/scene-utils/collect-subtree.ts +40 -0
- package/src/shadow-atlas.ts +244 -0
- package/src/ssao-buffers.ts +175 -0
- package/src/ssao-config.ts +61 -0
- package/src/ssao-data.ts +106 -0
- package/src/surface-format.ts +37 -0
- package/src/systems/active-camera.ts +116 -0
- package/src/systems/pass-selector.ts +49 -0
- package/src/systems/skin-palette-allocator.ts +294 -0
- package/src/systems/transparent-sort-config.ts +211 -0
- package/src/taa-history-store.ts +429 -0
- package/src/temporal-coverage.ts +106 -0
- package/src/temporal-frame-transaction.ts +301 -0
- package/src/temporal-inspection.ts +194 -0
- package/src/temporal-view.ts +174 -0
- package/src/tilemap/resolve-tileset-runtime.ts +72 -0
- package/src/tilemap-chunk-extract-system.ts +1307 -0
- package/src/typed-render-graph-primitives.ts +530 -0
- package/src/typed-shadow-passes.ts +195 -0
- package/src/urp-pipeline.ts +340 -0
|
@@ -0,0 +1,1768 @@
|
|
|
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 ShaderRegistry internal reflection, 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
|
+
DEFAULT_STANDARD_PBR_PARAM_SCHEMA,
|
|
27
|
+
DEFAULT_UNLIT_PARAM_SCHEMA,
|
|
28
|
+
type RegisteredMaterialShaderEntry,
|
|
29
|
+
type ShaderRegistry,
|
|
30
|
+
} from '@forgeax/engine-shader';
|
|
31
|
+
import {
|
|
32
|
+
type BindGroupLayoutEntry,
|
|
33
|
+
type DerivedMaterialInterface,
|
|
34
|
+
derive,
|
|
35
|
+
KNOWN_PASS_KINDS,
|
|
36
|
+
type MaterialRenderState,
|
|
37
|
+
type ParamSchemaEntry,
|
|
38
|
+
type PrimitiveTopology,
|
|
39
|
+
type VertexAttributeMap,
|
|
40
|
+
} from '@forgeax/engine-types';
|
|
41
|
+
import { GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX } from './gpu-stage';
|
|
42
|
+
import { createHdrpBindGroupLayoutDescriptor } from './hdrp-buffers';
|
|
43
|
+
import {
|
|
44
|
+
appendInjection,
|
|
45
|
+
buildPbrMaterialUserRegionEntries,
|
|
46
|
+
buildPbrViewBglEntries,
|
|
47
|
+
type PbrCaps,
|
|
48
|
+
} from './pbr-pipeline';
|
|
49
|
+
|
|
50
|
+
const DEFAULT_STANDARD_PBR_PROJECTION = derive(DEFAULT_STANDARD_PBR_PARAM_SCHEMA);
|
|
51
|
+
const DEFAULT_UNLIT_PROJECTION = derive(DEFAULT_UNLIT_PARAM_SCHEMA);
|
|
52
|
+
|
|
53
|
+
// Re-export KNOWN_PASS_KINDS from @forgeax/engine-types for single-file discoverability (charter F1).
|
|
54
|
+
export { KNOWN_PASS_KINDS };
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The engine-owned deferred material target layout. `fs_gbuffer` returns
|
|
58
|
+
* normal+roughness, albedo+metallic, and emissive+AO in this order.
|
|
59
|
+
*/
|
|
60
|
+
export const DEFERRED_COLOR_FORMATS: readonly GPUTextureFormat[] = [
|
|
61
|
+
'rgba16float',
|
|
62
|
+
'rgba8unorm',
|
|
63
|
+
'rgba16float',
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
/** Derive the color attachment shape for a material pass kind. */
|
|
67
|
+
export function colorFormatsForPassKind(
|
|
68
|
+
passKind: string,
|
|
69
|
+
defaultColorFormat: GPUTextureFormat,
|
|
70
|
+
): readonly GPUTextureFormat[] {
|
|
71
|
+
if (passKind === 'shadow-caster') return [];
|
|
72
|
+
if (passKind === 'deferred') return DEFERRED_COLOR_FORMATS;
|
|
73
|
+
return [defaultColorFormat];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
77
|
+
// PipelineSpec — immutable 4-axis data description (D-7: business-agnostic)
|
|
78
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Pipeline specification — immutable 4-axis data that completely determines
|
|
82
|
+
* what `device.createRenderPipeline(...)` does for a material shader pass.
|
|
83
|
+
*
|
|
84
|
+
* The 4 axes are:
|
|
85
|
+
* - `shader`: which WGSL source + material param schema + pass kind + variant set
|
|
86
|
+
* - `attachments`: color/depth/stencil formats + sample count (MSAA)
|
|
87
|
+
* - `geometry`: primitive topology + vertex attribute layout + index format
|
|
88
|
+
* - `renderState`: optional per-material render-state overrides (blend/cull/depth/stencil)
|
|
89
|
+
*
|
|
90
|
+
* Business-agnostic: no `'pbr'` / `'sprite'` / `'skybox'` strings pollute this
|
|
91
|
+
* type. BGL shape taxonomy is derived from `ShaderRegistry` internal reflection
|
|
92
|
+
* and never appears on the spec surface (plan-strategy D-7).
|
|
93
|
+
*
|
|
94
|
+
* @see plan-strategy §1 (4-axis) · D-7 (business-agnostic) · requirements §3.1
|
|
95
|
+
*/
|
|
96
|
+
export interface PipelineSpec {
|
|
97
|
+
/** Shader identity + routing axis. */
|
|
98
|
+
readonly shader: {
|
|
99
|
+
/** Registered shader identifier (e.g. `'forgeax::default-standard-pbr'`). */
|
|
100
|
+
readonly id: string;
|
|
101
|
+
/** Pass kind for attachment shape selection. Must be in {@link KNOWN_PASS_KINDS} or registered. */
|
|
102
|
+
readonly passKind: string;
|
|
103
|
+
/** Shader variant set string (e.g. `'SKIN_AVAILABLE=1'`). `undefined` for no variant. */
|
|
104
|
+
readonly variantSet: string | undefined;
|
|
105
|
+
/** Fragment entry point; omitted means the shader's standard `fs_main`. */
|
|
106
|
+
readonly fragmentEntry?: string | undefined;
|
|
107
|
+
};
|
|
108
|
+
/** Attachment format + sample-count axis. */
|
|
109
|
+
readonly attachments: {
|
|
110
|
+
/** Colour attachment formats in draw order. Empty for depth-only passes (shadow-caster). */
|
|
111
|
+
readonly colorFormats: readonly GPUTextureFormat[];
|
|
112
|
+
/** Depth-stencil format, or `undefined` when no depth target is bound. */
|
|
113
|
+
readonly depthFormat: GPUTextureFormat | undefined;
|
|
114
|
+
/** Sample count: 1 (no MSAA) or 4 (4x MSAA). */
|
|
115
|
+
readonly sampleCount: 1 | 4;
|
|
116
|
+
};
|
|
117
|
+
/** Geometry layout axis. */
|
|
118
|
+
readonly geometry: {
|
|
119
|
+
/** Primitive topology baked into the PSO. */
|
|
120
|
+
readonly topology: PrimitiveTopology;
|
|
121
|
+
/** Strip index format (uint16 / uint32), only meaningful for strip topologies. */
|
|
122
|
+
readonly stripIndexFormat?: 'uint16' | 'uint32' | undefined;
|
|
123
|
+
/** Per-vertex attribute layout (position / normal / uv / tangent / skinIndex / skinWeight). */
|
|
124
|
+
readonly vertexLayout: VertexAttributeMap;
|
|
125
|
+
/** Canonical geometry-owned projection; derived when omitted for legacy callers. */
|
|
126
|
+
readonly vertexLayoutProjection?: VertexLayoutProjection | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* Number of UV sets declared by the shader (derived from @location reflection).
|
|
129
|
+
* Forwarded to deriveVertexBufferLayout for clamp-to-last alias (D-1 / D-4).
|
|
130
|
+
* Undefined = fallback to mesh-provided UV count (no clamping).
|
|
131
|
+
* feat-20260629-multi-uv-set-support m3-w5: plumbed placeholder.
|
|
132
|
+
* TODO(M4/m4-w3): fill from naga reflection JSON when available.
|
|
133
|
+
*/
|
|
134
|
+
readonly shaderUvSetCount?: number | undefined;
|
|
135
|
+
};
|
|
136
|
+
/** Per-material render-state overrides (optional — engine defaults applied when absent). */
|
|
137
|
+
readonly renderState: MaterialRenderState | undefined;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
141
|
+
// PipelineSpecError — closed union (5 + 2 transit codes)
|
|
142
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Closed union of PipelineSpec error codes.
|
|
146
|
+
*
|
|
147
|
+
* 5 business codes:
|
|
148
|
+
* - `'spec-inconsistent'`: axis mutual exclusion violated
|
|
149
|
+
* - `'unknown-pass-kind'`: passKind not in KNOWN_PASS_KINDS or registered
|
|
150
|
+
* - `'shader-bgl-reflection-mismatch'`: reflected BGL shape != shader declaration
|
|
151
|
+
* - `'attachment-format-incompatible'`: depth/stencil format vs PSO mismatch
|
|
152
|
+
* - `'unsupported-vertex-layout'`: vertex attributes don't match shader vs_main
|
|
153
|
+
*
|
|
154
|
+
* 2 transit codes:
|
|
155
|
+
* - `'pipeline-build-failed'`: wraps RhiError from device.createRenderPipeline
|
|
156
|
+
* - `'shader-not-registered'`: ShaderRegistry.lookup returned undefined
|
|
157
|
+
*
|
|
158
|
+
* @see requirements §3.4 · AC-10 · charter P3
|
|
159
|
+
*/
|
|
160
|
+
export type PipelineSpecErrorCode =
|
|
161
|
+
| 'spec-inconsistent'
|
|
162
|
+
| 'unknown-pass-kind'
|
|
163
|
+
| 'shader-bgl-reflection-mismatch'
|
|
164
|
+
| 'attachment-format-incompatible'
|
|
165
|
+
| 'unsupported-vertex-layout'
|
|
166
|
+
| 'pipeline-build-failed'
|
|
167
|
+
| 'shader-not-registered';
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Structured pipeline-spec error — carries `.code` (discriminated union) +
|
|
171
|
+
* `.detail` (narrowed per code) + `.hint` (AI-user actionable prose).
|
|
172
|
+
*
|
|
173
|
+
* Inherits from `Error` so it integrates with existing catch blocks; the
|
|
174
|
+
* `.code` field enables exhaustive `switch` narrowing without string parsing
|
|
175
|
+
* (charter P3).
|
|
176
|
+
*/
|
|
177
|
+
export class PipelineSpecError extends Error {
|
|
178
|
+
readonly code: PipelineSpecErrorCode;
|
|
179
|
+
/**
|
|
180
|
+
* Narrowed detail payload — shape depends on `code`.
|
|
181
|
+
*
|
|
182
|
+
* - `'spec-inconsistent'`: `{ reason: string }`
|
|
183
|
+
* - `'unknown-pass-kind'`: `{ expected: readonly string[]; actual: string; hint?: string }`
|
|
184
|
+
* - `'shader-bgl-reflection-mismatch'`: `{ reflected: unknown; declared: unknown }`
|
|
185
|
+
* - `'attachment-format-incompatible'`: `{ reason: string; expected?: string; actual?: string }`
|
|
186
|
+
* - `'unsupported-vertex-layout'`: `{ specAttrs: string[]; shaderAttrs: string[] }`
|
|
187
|
+
* - `'pipeline-build-failed'`: `{ gpuMessage?: string; cause?: unknown }`
|
|
188
|
+
* - `'shader-not-registered'`: `{ shaderId: string; hint?: string }`
|
|
189
|
+
*/
|
|
190
|
+
readonly detail: Record<string, unknown>;
|
|
191
|
+
|
|
192
|
+
constructor(args: {
|
|
193
|
+
code: PipelineSpecErrorCode;
|
|
194
|
+
detail: Record<string, unknown>;
|
|
195
|
+
hint?: string;
|
|
196
|
+
}) {
|
|
197
|
+
super(
|
|
198
|
+
args.hint !== undefined
|
|
199
|
+
? `PipelineSpecError [${args.code}]: ${args.hint}`
|
|
200
|
+
: `PipelineSpecError [${args.code}]`,
|
|
201
|
+
);
|
|
202
|
+
this.name = 'PipelineSpecError';
|
|
203
|
+
this.code = args.code;
|
|
204
|
+
this.detail = args.detail;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
209
|
+
// BindGroupLayoutShape — reflection-derived BGL descriptor
|
|
210
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Bind group layout shape derived from ShaderRegistry reflection.
|
|
214
|
+
*
|
|
215
|
+
* `entries` mirrors `GPUBindGroupLayoutDescriptor.entries` — the binding
|
|
216
|
+
* slot layout the shader expects for a given variantSet.
|
|
217
|
+
*/
|
|
218
|
+
export interface BindGroupLayoutShape {
|
|
219
|
+
readonly entries: readonly BindGroupLayoutEntry[];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
223
|
+
// deriveBglShapeFromShader — reflection helper (D-1)
|
|
224
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Derive BGL shape from a registered shader entry's paramSchema.
|
|
228
|
+
*
|
|
229
|
+
* Pure function: same `entry` always yields the same shape (no variant-set
|
|
230
|
+
* dispatch — that role moved into `BglKind` after D-13's closed-union
|
|
231
|
+
* dispatch landed; see plan-decisions.md). The `_variantSet` parameter is
|
|
232
|
+
* preserved for backward signature compat but ignored — variant routing is
|
|
233
|
+
* now explicit at the BglKind level (see `buildBindGroupLayoutDescriptor`
|
|
234
|
+
* arms `pbr-skin-mesh-array` vs `hdrp-7-slot` vs `pbr-mesh-array`).
|
|
235
|
+
*
|
|
236
|
+
* This helper lives in `pipeline-spec.ts` (not ShaderRegistry) per D-1:
|
|
237
|
+
* it wraps the existing `derive(paramSchema).bglEntries` from
|
|
238
|
+
* `@forgeax/engine-types` so cacheKeyOf can hash BGL shape deterministically
|
|
239
|
+
* without expanding the ShaderRegistry public interface.
|
|
240
|
+
*
|
|
241
|
+
* @param entry - material shader entry from ShaderRegistry.findMaterialArtifact
|
|
242
|
+
* @param _variantSet - unused (post D-13); kept for backward signature compat
|
|
243
|
+
* @returns the BGL shape for the given entry
|
|
244
|
+
* @see plan-decisions.md D-13
|
|
245
|
+
*/
|
|
246
|
+
export function deriveBglShapeFromShader(
|
|
247
|
+
entry: RegisteredMaterialShaderEntry,
|
|
248
|
+
_variantSet?: string | undefined,
|
|
249
|
+
): BindGroupLayoutShape {
|
|
250
|
+
// derive() from @forgeax/engine-types is the actual SSOT; we invoke it
|
|
251
|
+
// here so that cacheKeyOf can hash BGL shape deterministically.
|
|
252
|
+
return {
|
|
253
|
+
entries: entry.paramSchemaProjection.derivedInterface.bglEntries,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
258
|
+
// renderStateHashSuffix — deterministic hash of MaterialRenderState
|
|
259
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Material snapshots hand the renderer immutable render-state objects. Keep
|
|
263
|
+
* the serialized suffix by object identity just like the vertex-layout
|
|
264
|
+
* digest below; the hot path otherwise sorts keys and serializes the same
|
|
265
|
+
* state once per renderable. Callers must not mutate a MaterialRenderState
|
|
266
|
+
* after passing it to the renderer (the PipelineSpec contract is immutable).
|
|
267
|
+
*/
|
|
268
|
+
const RENDER_STATE_HASH_CACHE = new WeakMap<object, string>();
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Deterministic hash suffix for MaterialRenderState (sorted keys, JSON.stringify).
|
|
272
|
+
*
|
|
273
|
+
* Returns `''` when `renderState` is `undefined` or has zero entries,
|
|
274
|
+
* preserving cache-key byte-compatibility with the pre-M1 shape.
|
|
275
|
+
*/
|
|
276
|
+
export function renderStateHash(renderState: MaterialRenderState | undefined): string {
|
|
277
|
+
if (renderState === undefined) return '';
|
|
278
|
+
const cached = RENDER_STATE_HASH_CACHE.get(renderState);
|
|
279
|
+
if (cached !== undefined) return cached;
|
|
280
|
+
const sorted = Object.keys(renderState).sort();
|
|
281
|
+
if (sorted.length === 0) {
|
|
282
|
+
RENDER_STATE_HASH_CACHE.set(renderState, '');
|
|
283
|
+
return '';
|
|
284
|
+
}
|
|
285
|
+
const payload: Record<string, unknown> = {};
|
|
286
|
+
for (const k of sorted) {
|
|
287
|
+
const v = renderState[k as keyof MaterialRenderState];
|
|
288
|
+
if (v !== undefined) payload[k] = v;
|
|
289
|
+
}
|
|
290
|
+
const result = `:${JSON.stringify(payload)}`;
|
|
291
|
+
RENDER_STATE_HASH_CACHE.set(renderState, result);
|
|
292
|
+
return result;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
296
|
+
// 6 pure derive functions (M1-T2)
|
|
297
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Compute a deterministic cache key from a PipelineSpec.
|
|
301
|
+
*
|
|
302
|
+
* The key covers all 4 axes + BGL shape hash (derived from ShaderRegistry
|
|
303
|
+
* reflection via {@link deriveBglShapeFromShader}). Two specs that produce
|
|
304
|
+
* the same cache key MUST produce byte-identical PSO descriptors.
|
|
305
|
+
*
|
|
306
|
+
* Algorithm: concatenate each axis segment with `:` separators, hash the
|
|
307
|
+
* BGL shape for compactness, and emit a single cache-key string.
|
|
308
|
+
*
|
|
309
|
+
* @see plan-strategy §3.1 · requirements AC-02
|
|
310
|
+
*/
|
|
311
|
+
export function cacheKeyOf(spec: PipelineSpec): string {
|
|
312
|
+
const { shader, attachments, geometry, renderState } = spec;
|
|
313
|
+
const topoSegment = geometry.topology;
|
|
314
|
+
const stripSegment =
|
|
315
|
+
(topoSegment === 'line-strip' || topoSegment === 'triangle-strip') &&
|
|
316
|
+
geometry.stripIndexFormat !== undefined
|
|
317
|
+
? `:${geometry.stripIndexFormat}`
|
|
318
|
+
: '';
|
|
319
|
+
|
|
320
|
+
// Hash vertexLayout deterministically — the digest is identity-cached for
|
|
321
|
+
// immutable mesh-asset maps reused across submeshes and frames.
|
|
322
|
+
const vlDigest =
|
|
323
|
+
geometry.vertexLayoutProjection?.digest ??
|
|
324
|
+
deriveVertexLayoutProjection(geometry.vertexLayout).digest;
|
|
325
|
+
|
|
326
|
+
const uvSetCountSegment =
|
|
327
|
+
geometry.shaderUvSetCount !== undefined ? `:uvsc${geometry.shaderUvSetCount}` : '';
|
|
328
|
+
|
|
329
|
+
// bug-20260708 M2 (b): sentinel `~` distinguishes `variantSet=undefined`
|
|
330
|
+
// (no-variant / default-variant request) from canonical all-true key `''`
|
|
331
|
+
// (all variant axes true). Prior `?? ''` collapsed the two into the same
|
|
332
|
+
// cache key, causing the first-cached pipeline to win and unrelated
|
|
333
|
+
// variantSet requests to reuse its shader module (research R-11 / R-12).
|
|
334
|
+
// `~` (ASCII 0x7E) is a reserved sentinel char — no legitimate
|
|
335
|
+
// variantSet literal contains it; guarded by
|
|
336
|
+
// `pipeline-cache-keying.unit.test.ts` sentinel-conflict assertions.
|
|
337
|
+
const variantSegment = shader.variantSet === undefined ? '~' : shader.variantSet;
|
|
338
|
+
const fragmentEntrySegment = shader.fragmentEntry ?? 'fs_main';
|
|
339
|
+
return (
|
|
340
|
+
[
|
|
341
|
+
shader.id,
|
|
342
|
+
shader.passKind,
|
|
343
|
+
variantSegment,
|
|
344
|
+
fragmentEntrySegment,
|
|
345
|
+
attachments.colorFormats.join(','),
|
|
346
|
+
attachments.depthFormat ?? '',
|
|
347
|
+
String(attachments.sampleCount),
|
|
348
|
+
topoSegment,
|
|
349
|
+
stripSegment,
|
|
350
|
+
`vl:${vlDigest}`,
|
|
351
|
+
renderStateHash(renderState),
|
|
352
|
+
].join(':') + uvSetCountSegment
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Build a `GPURenderPipelineDescriptor` from a PipelineSpec + shader modules.
|
|
358
|
+
*
|
|
359
|
+
* Pure derivation: same (spec, modules) always produces the same descriptor.
|
|
360
|
+
* Consumed by `getOrBuildPipeline` on cache miss; also available as a public
|
|
361
|
+
* helper for AI users who want the descriptor shape without going through the
|
|
362
|
+
* cache entrypoint.
|
|
363
|
+
*
|
|
364
|
+
* @param spec - the pipeline spec (4 axes)
|
|
365
|
+
* @param modules - `{ vertex: GPUShaderModule; fragment: GPUShaderModule }`
|
|
366
|
+
* @returns a complete WebGPU render-pipeline descriptor
|
|
367
|
+
* @see plan-strategy §3.2 · requirements AC-02
|
|
368
|
+
*/
|
|
369
|
+
export function buildPipelineDescriptor(
|
|
370
|
+
spec: PipelineSpec,
|
|
371
|
+
modules: {
|
|
372
|
+
vertex: unknown;
|
|
373
|
+
fragment: unknown;
|
|
374
|
+
vertexEntryPoint?: string;
|
|
375
|
+
fragmentEntryPoint?: string;
|
|
376
|
+
layout?: unknown;
|
|
377
|
+
},
|
|
378
|
+
): Record<string, unknown> {
|
|
379
|
+
// M2-T4: derive vertex buffers from spec.geometry.vertexLayout via
|
|
380
|
+
// deriveVertexBufferLayout (imported from vertex-attribute-layout.ts).
|
|
381
|
+
// Empty vertexLayout (fullscreen-post passes) → [].
|
|
382
|
+
// Non-empty (material shaders) → interleaved single-buffer layout.
|
|
383
|
+
//
|
|
384
|
+
// Entry points default to 'vs_main' / 'fs_main' for the 3 standard material
|
|
385
|
+
// shaders; fullscreen-post passes (skybox 'skybox_fs', SSAO 'vs_ssao' / 'fs_ssao_calc')
|
|
386
|
+
// pass custom entry points through the modules parameter.
|
|
387
|
+
//
|
|
388
|
+
// The optional `layout` field, when present, is forwarded to the descriptor
|
|
389
|
+
// so that the provider can detect it is already set and avoid overwriting.
|
|
390
|
+
|
|
391
|
+
const { attachments, geometry, renderState } = spec;
|
|
392
|
+
|
|
393
|
+
const isShadowCaster = spec.shader.passKind === 'shadow-caster';
|
|
394
|
+
const isStrip = geometry.topology === 'line-strip' || geometry.topology === 'triangle-strip';
|
|
395
|
+
|
|
396
|
+
// A supplied projection is already the geometry owner's immutable GPU
|
|
397
|
+
// descriptor. Do not re-derive it from the caller's attribute map: that
|
|
398
|
+
// would permit a stale map to disagree with the uploaded interleaved bytes.
|
|
399
|
+
// Legacy callers without a projection retain the UV aliasing derivation.
|
|
400
|
+
const vertexBuffers =
|
|
401
|
+
geometry.vertexLayoutProjection === undefined
|
|
402
|
+
? deriveVertexBufferLayout(geometry.vertexLayout, {
|
|
403
|
+
...(geometry.shaderUvSetCount !== undefined
|
|
404
|
+
? { shaderUvSetCount: geometry.shaderUvSetCount }
|
|
405
|
+
: {}),
|
|
406
|
+
})
|
|
407
|
+
: geometry.vertexLayoutProjection.attributes.length === 0
|
|
408
|
+
? []
|
|
409
|
+
: [
|
|
410
|
+
{
|
|
411
|
+
arrayStride: geometry.vertexLayoutProjection.arrayStride,
|
|
412
|
+
attributes: geometry.vertexLayoutProjection.attributes.map(
|
|
413
|
+
({ shaderLocation, offset, format }) => ({
|
|
414
|
+
shaderLocation,
|
|
415
|
+
offset,
|
|
416
|
+
format,
|
|
417
|
+
}),
|
|
418
|
+
),
|
|
419
|
+
},
|
|
420
|
+
];
|
|
421
|
+
|
|
422
|
+
const descriptor: Record<string, unknown> = {
|
|
423
|
+
vertex: {
|
|
424
|
+
module: modules.vertex,
|
|
425
|
+
entryPoint: modules.vertexEntryPoint ?? 'vs_main',
|
|
426
|
+
buffers: vertexBuffers,
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
// Fragment stage: absent for shadow-caster (depth-only), present for forward.
|
|
431
|
+
if (!isShadowCaster && attachments.colorFormats.length > 0) {
|
|
432
|
+
descriptor.fragment = {
|
|
433
|
+
module: modules.fragment,
|
|
434
|
+
entryPoint: modules.fragmentEntryPoint ?? 'fs_main',
|
|
435
|
+
targets: attachments.colorFormats.map((fmt) => {
|
|
436
|
+
const target: Record<string, unknown> = { format: fmt };
|
|
437
|
+
if (renderState?.blend !== undefined) {
|
|
438
|
+
target.blend = renderState.blend;
|
|
439
|
+
}
|
|
440
|
+
return target;
|
|
441
|
+
}),
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Layout: forward if provided by caller (fullscreen-post passes set it).
|
|
446
|
+
if (modules.layout !== undefined) {
|
|
447
|
+
descriptor.layout = modules.layout;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Primitive state.
|
|
451
|
+
const primitive: Record<string, unknown> = {
|
|
452
|
+
topology: geometry.topology,
|
|
453
|
+
cullMode: renderState?.cullMode ?? 'back',
|
|
454
|
+
frontFace: renderState?.frontFace ?? 'ccw',
|
|
455
|
+
};
|
|
456
|
+
if (isStrip && geometry.stripIndexFormat !== undefined) {
|
|
457
|
+
primitive.stripIndexFormat = geometry.stripIndexFormat;
|
|
458
|
+
}
|
|
459
|
+
descriptor.primitive = primitive;
|
|
460
|
+
|
|
461
|
+
// Depth-stencil state.
|
|
462
|
+
if (attachments.depthFormat !== undefined) {
|
|
463
|
+
const ds: Record<string, unknown> = {
|
|
464
|
+
format: attachments.depthFormat,
|
|
465
|
+
depthWriteEnabled: renderState?.depthWriteEnabled ?? true,
|
|
466
|
+
depthCompare: renderState?.depthCompare ?? 'less',
|
|
467
|
+
};
|
|
468
|
+
if (renderState?.stencilReadMask !== undefined) {
|
|
469
|
+
ds.stencilReadMask = renderState.stencilReadMask;
|
|
470
|
+
}
|
|
471
|
+
if (renderState?.stencilWriteMask !== undefined) {
|
|
472
|
+
ds.stencilWriteMask = renderState.stencilWriteMask;
|
|
473
|
+
}
|
|
474
|
+
if (renderState?.stencil !== undefined) {
|
|
475
|
+
ds.stencilFront = renderState.stencil;
|
|
476
|
+
ds.stencilBack = renderState.stencil;
|
|
477
|
+
}
|
|
478
|
+
descriptor.depthStencil = ds;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Multisample: absent for sampleCount=1 (undefined). For any value > 1,
|
|
482
|
+
// emit { count: sampleCount } so forward-compat sample counts (2, 8, …)
|
|
483
|
+
// flow through to the descriptor without requiring a type change.
|
|
484
|
+
if (attachments.sampleCount > 1) {
|
|
485
|
+
descriptor.multisample = {
|
|
486
|
+
count: attachments.sampleCount,
|
|
487
|
+
...(renderState?.alphaToCoverageEnabled === true && { alphaToCoverageEnabled: true }),
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return descriptor;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
495
|
+
// BglKind dispatch (M3 / D-13) — closed union of BGL shapes the runtime ships
|
|
496
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Closed union of bind-group-layout shapes the runtime constructs.
|
|
500
|
+
*
|
|
501
|
+
* Each kind names one physically distinct BGL the runtime has historically
|
|
502
|
+
* built by hand. {@link buildBindGroupLayoutDescriptor} dispatches on this
|
|
503
|
+
* union so every `device.createBindGroupLayout(...)` call site shares one
|
|
504
|
+
* SSOT for entries / labels (plan-strategy §3.2; D-13 round-2 decision).
|
|
505
|
+
*
|
|
506
|
+
* Three groups by derivation source:
|
|
507
|
+
* 1. Shader-derived (paramSchema reflection + injection chain):
|
|
508
|
+
* - `'pbr-material-merged'` — derived user region + Skylight 7 + lightmap 4
|
|
509
|
+
* - `'unlit-material'` — 7 entries: base PBR material only (no inject)
|
|
510
|
+
* - `'hdrp-7-slot'` — 7 entries (binding 0 + 3..8): HDRP cluster + SSAO group(2) BGL
|
|
511
|
+
* 2. Caps-driven literal shapes (no shader):
|
|
512
|
+
* - `'pbr-view'` — 10 entries: view UBO + lights + 6 shadow bindings
|
|
513
|
+
* (directional 3/4, point 5/6, cascade 7, spot atlas 8, spot
|
|
514
|
+
* lightViewProj matrices 9 — feat-20260625)
|
|
515
|
+
* - `'pbr-mesh-array'` — 1 entry: per-entity mesh SSBO (dynamic-offset)
|
|
516
|
+
* - `'pbr-instances'` — 1 entry: per-instance SSBO (no dynamic-offset)
|
|
517
|
+
* - `'pbr-skin-mesh-array'` — 3 entries: meshes + current/previous skin palettes
|
|
518
|
+
* 3. Attachment-driven (fullscreen post-process):
|
|
519
|
+
* - `'fullscreen-post'` — 2 entries: input texture + sampler. The texture
|
|
520
|
+
* `sampleType` is derived from `spec.attachments` (plan §R3 fix):
|
|
521
|
+
* `'depth32float'` → `'depth'`; `'r32float'` → `'unfilterable-float'`;
|
|
522
|
+
* else → `'float'`.
|
|
523
|
+
* - `'fullscreen-post-with-params'` — 3 entries: the same texture@0 +
|
|
524
|
+
* sampler@1 as `'fullscreen-post'`, plus a `buffer@2` uniform for the
|
|
525
|
+
* per-frame params UBO (feat-20260621 D-2: `entry.params !== undefined`
|
|
526
|
+
* passes route here; the layout stays group(1), q3=B). `'fullscreen-post'`
|
|
527
|
+
* stays byte-identical so param-less consumers degrade with no change.
|
|
528
|
+
* - `'fullscreen-post-with-scene-depth-msaa'` — the depth-read layout with
|
|
529
|
+
* `texture.multisampled=true`, selected for a 4-sample scene depth target.
|
|
530
|
+
*/
|
|
531
|
+
export type BglKind =
|
|
532
|
+
| 'pbr-view'
|
|
533
|
+
| 'pbr-material-merged'
|
|
534
|
+
| 'pbr-mesh-array'
|
|
535
|
+
| 'pbr-instances'
|
|
536
|
+
| 'pbr-skin-mesh-array'
|
|
537
|
+
| 'unlit-material'
|
|
538
|
+
| 'hdrp-7-slot'
|
|
539
|
+
| 'fullscreen-post'
|
|
540
|
+
| 'fullscreen-post-with-params'
|
|
541
|
+
| 'fullscreen-post-with-scene-depth'
|
|
542
|
+
| 'fullscreen-post-with-scene-depth-msaa'
|
|
543
|
+
| 'fullscreen-post-with-gbuffer-depth';
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Output shape of {@link buildBindGroupLayoutDescriptor}: matches the RHI
|
|
547
|
+
* `BindGroupLayoutDescriptor` (label + entries with `ExplicitUndefined`) so
|
|
548
|
+
* the result can be passed directly to `device.createBindGroupLayout(...)`.
|
|
549
|
+
*
|
|
550
|
+
* `entries` is a mutable `Array` to match `GPUBindGroupLayoutDescriptor`
|
|
551
|
+
* (WebGPU types declare it mutable). Callers MUST treat the array as
|
|
552
|
+
* read-only — the dispatcher freezes neither the array nor its entries
|
|
553
|
+
* for hot-path performance.
|
|
554
|
+
*/
|
|
555
|
+
export interface BindGroupLayoutDescriptorOutput {
|
|
556
|
+
readonly label: string | undefined;
|
|
557
|
+
readonly entries: GPUBindGroupLayoutEntry[];
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Build a `GPUBindGroupLayoutDescriptor` from a PipelineSpec, dispatching on
|
|
562
|
+
* `options.kind` to one of 9 closed BGL shapes (D-13 round-2).
|
|
563
|
+
*
|
|
564
|
+
* Shader-derived kinds (`'pbr-material-merged'` / `'unlit-material'` /
|
|
565
|
+
* `'hdrp-7-slot'`) require `options.registry` to look up the shader entry
|
|
566
|
+
* and reflect its `paramSchema` via {@link deriveBglShapeFromShader}; they
|
|
567
|
+
* compose the per-entry injection chain (Skylight + lightmap for material;
|
|
568
|
+
* HDRP variantSet for cluster-forward).
|
|
569
|
+
*
|
|
570
|
+
* Caps-driven kinds (`'pbr-view'` / `'pbr-mesh-array'` / `'pbr-instances'` /
|
|
571
|
+
* `'pbr-skin-mesh-array'`) require `options.caps` for the storage-buffer
|
|
572
|
+
* vs uniform-buffer fallback (RhiCaps.storageBuffer; PBR feat-20260526 M3 /
|
|
573
|
+
* w9). They are wholly determined by the caps shape.
|
|
574
|
+
*
|
|
575
|
+
* Attachment-driven kind (`'fullscreen-post'`) reads
|
|
576
|
+
* `spec.attachments.depthFormat` and `spec.attachments.colorFormats[0]` to
|
|
577
|
+
* pick the texture binding's `sampleType` (R3 fix: `'depth32float'` → `'depth'`,
|
|
578
|
+
* `'r32float'` → `'unfilterable-float'`, else → `'float'`).
|
|
579
|
+
*
|
|
580
|
+
* @param spec - the pipeline spec (axis source for reflection / caps fallback)
|
|
581
|
+
* @param options.kind - which BGL shape to build (closed {@link BglKind} union)
|
|
582
|
+
* @param options.registry - ShaderRegistry for shader-derived kinds
|
|
583
|
+
* @param options.caps - caps shape for caps-driven kinds (storageBuffer)
|
|
584
|
+
* @returns a WebGPU bind-group-layout descriptor (entries + label)
|
|
585
|
+
* @see plan-strategy §3.2 · plan-decisions D-13 · requirements AC-02
|
|
586
|
+
*/
|
|
587
|
+
/**
|
|
588
|
+
* Resolve the material paramSchema for a per-shader user-region BGL derivation.
|
|
589
|
+
*
|
|
590
|
+
* Priority (D-1): explicit `options.materialParamSchema` > registry lookup of
|
|
591
|
+
* `spec.shader.id` > `undefined` (the user-region builder then falls back to
|
|
592
|
+
* the built-in standard-PBR 4-texture schema, whose user region is 9 entries).
|
|
593
|
+
*/
|
|
594
|
+
function resolveMaterialProjection(
|
|
595
|
+
spec: PipelineSpec,
|
|
596
|
+
options: { registry?: ShaderRegistry; materialParamSchema?: readonly ParamSchemaEntry[] },
|
|
597
|
+
): DerivedMaterialInterface | undefined {
|
|
598
|
+
if (options.registry !== undefined) {
|
|
599
|
+
const lookup = options.registry.findMaterialArtifact(spec.shader.id);
|
|
600
|
+
if (lookup.ok) return lookup.value.paramSchemaProjection.derivedInterface;
|
|
601
|
+
}
|
|
602
|
+
// Compatibility seam for callers that have not reached ShaderRegistry
|
|
603
|
+
// admission yet. Runtime registry callers always take the branch above.
|
|
604
|
+
if (options.materialParamSchema !== undefined) return derive(options.materialParamSchema);
|
|
605
|
+
return undefined;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
export function buildBindGroupLayoutDescriptor(
|
|
609
|
+
spec: PipelineSpec,
|
|
610
|
+
options: {
|
|
611
|
+
kind: BglKind;
|
|
612
|
+
registry?: ShaderRegistry;
|
|
613
|
+
caps?: PbrCaps;
|
|
614
|
+
/**
|
|
615
|
+
* Material paramSchema for the per-shader user-region derivation
|
|
616
|
+
* (`'pbr-material-merged'` / `'unlit-material'`). When supplied it is the
|
|
617
|
+
* authoritative source for the user-region BGL shape (D-1); when omitted,
|
|
618
|
+
* `buildPbrMaterialUserRegionEntries` falls back to the built-in
|
|
619
|
+
* standard-PBR 4-texture schema (user region is 9 entries), so
|
|
620
|
+
* the caps-driven `buildPbrPipelineLayouts` seam keeps working unchanged.
|
|
621
|
+
* A registry + resolvable shader id takes precedence over this field.
|
|
622
|
+
*/
|
|
623
|
+
materialParamSchema?: readonly ParamSchemaEntry[];
|
|
624
|
+
},
|
|
625
|
+
): BindGroupLayoutDescriptorOutput {
|
|
626
|
+
switch (options.kind) {
|
|
627
|
+
case 'pbr-view': {
|
|
628
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
629
|
+
return {
|
|
630
|
+
label: 'pbr-view-bgl',
|
|
631
|
+
entries: buildPbrViewBglEntries(caps),
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
case 'pbr-mesh-array': {
|
|
635
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
636
|
+
const meshBufType: GPUBufferBindingType = caps.storageBuffer
|
|
637
|
+
? 'read-only-storage'
|
|
638
|
+
: 'uniform';
|
|
639
|
+
// sprite-lit's fragment stage does not read the mesh SSBO -- worldPos
|
|
640
|
+
// is carried through the VsOut interpolant. Visibility is kept widened
|
|
641
|
+
// to VERTEX|FRAGMENT because the BGL JSON is compared byte-identically
|
|
642
|
+
// across the sprite / sprite-lit / PBR pipelines that share this
|
|
643
|
+
// descriptor; narrowing here would change every sibling pipeline's
|
|
644
|
+
// BGL fingerprint. WebGPU rejects createRenderPipeline when a fragment
|
|
645
|
+
// stage accesses a binding whose BGL visibility excludes FRAGMENT --
|
|
646
|
+
// widening is permissive (validation-only, no perf cost).
|
|
647
|
+
return {
|
|
648
|
+
label: 'pbr-mesh-array-bgl',
|
|
649
|
+
entries: [
|
|
650
|
+
{
|
|
651
|
+
binding: 0,
|
|
652
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
653
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
654
|
+
},
|
|
655
|
+
],
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
case 'pbr-instances': {
|
|
659
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
660
|
+
const meshBufType: GPUBufferBindingType = caps.storageBuffer
|
|
661
|
+
? 'read-only-storage'
|
|
662
|
+
: 'uniform';
|
|
663
|
+
return {
|
|
664
|
+
label: 'pbr-instances-bgl',
|
|
665
|
+
entries: [
|
|
666
|
+
{
|
|
667
|
+
binding: 0,
|
|
668
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
669
|
+
buffer: { type: meshBufType, hasDynamicOffset: false },
|
|
670
|
+
},
|
|
671
|
+
],
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
case 'pbr-skin-mesh-array': {
|
|
675
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
676
|
+
const meshBufType: GPUBufferBindingType = caps.storageBuffer
|
|
677
|
+
? 'read-only-storage'
|
|
678
|
+
: 'uniform';
|
|
679
|
+
return {
|
|
680
|
+
label: 'pbr-skin-mesh-array-bgl',
|
|
681
|
+
entries: [
|
|
682
|
+
{
|
|
683
|
+
binding: 0,
|
|
684
|
+
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
685
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
binding: 1,
|
|
689
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
690
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
binding: 2,
|
|
694
|
+
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
695
|
+
buffer: { type: meshBufType, hasDynamicOffset: true },
|
|
696
|
+
},
|
|
697
|
+
],
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
case 'pbr-material-merged': {
|
|
701
|
+
// Material BGL: per-shader user-region (derive(paramSchema).bglEntries)
|
|
702
|
+
// + IBL injection (7). Emissive and occlusion are material texture
|
|
703
|
+
// parameters in the derived user-region; they are not a second
|
|
704
|
+
// engine-owned lightmap ledger.
|
|
705
|
+
//
|
|
706
|
+
// Schema source priority (D-1): explicit materialParamSchema option >
|
|
707
|
+
// registry lookup of spec.shader.id > built-in standard-PBR fallback.
|
|
708
|
+
const resolvedProjection =
|
|
709
|
+
resolveMaterialProjection(spec, options) ?? DEFAULT_STANDARD_PBR_PROJECTION;
|
|
710
|
+
const userRegion = buildPbrMaterialUserRegionEntries(resolvedProjection);
|
|
711
|
+
const afterIbl = [...userRegion, ...appendInjection(userRegion, 'ibl')];
|
|
712
|
+
return {
|
|
713
|
+
label: 'pbr-material-skylight-bgl',
|
|
714
|
+
entries: afterIbl,
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
case 'unlit-material': {
|
|
718
|
+
// Unlit material BGL: per-shader user-region only. No IBL/lightmap
|
|
719
|
+
// injection (D-5 round-4: unlit demos do not pay for IBL state).
|
|
720
|
+
const resolvedProjection =
|
|
721
|
+
resolveMaterialProjection(spec, options) ?? DEFAULT_UNLIT_PROJECTION;
|
|
722
|
+
return {
|
|
723
|
+
label: 'unlit-material-bgl',
|
|
724
|
+
entries: buildPbrMaterialUserRegionEntries(resolvedProjection),
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
case 'hdrp-7-slot': {
|
|
728
|
+
// HDRP unified BGL for group(2): 9 entries (binding 0 + 3..8). The
|
|
729
|
+
// shape depends on caps.storageBuffer for the cluster-buffer fallback.
|
|
730
|
+
const caps = options.caps ?? { storageBuffer: true };
|
|
731
|
+
const desc = createHdrpBindGroupLayoutDescriptor(caps.storageBuffer);
|
|
732
|
+
if (options.registry !== undefined) {
|
|
733
|
+
const lookup = options.registry.findMaterialArtifact(spec.shader.id);
|
|
734
|
+
if (lookup.ok) {
|
|
735
|
+
deriveBglShapeFromShader(lookup.value, spec.shader.variantSet);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
return {
|
|
739
|
+
label: desc.label ?? 'hdrp-unified-bgl-group2',
|
|
740
|
+
entries: desc.entries ?? [],
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
case 'fullscreen-post': {
|
|
744
|
+
// Fullscreen post-process BGL: 2 entries (input texture + sampler).
|
|
745
|
+
// R3 fix: derive sampleType from spec.attachments. Depth attachments
|
|
746
|
+
// (depth32float) need `sampleType: 'depth'`; r32float needs
|
|
747
|
+
// `'unfilterable-float'`; everything else (rgba8unorm-srgb, rgba16float,
|
|
748
|
+
// bgra8unorm, …) is filterable `'float'`.
|
|
749
|
+
return {
|
|
750
|
+
label: 'fullscreen-post-bgl',
|
|
751
|
+
entries: buildFullscreenPostInputEntries(spec),
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
case 'fullscreen-post-with-params': {
|
|
755
|
+
// feat-20260621 D-2: the same input texture@0 + sampler@1 as
|
|
756
|
+
// 'fullscreen-post', plus binding 2 = per-frame params UBO (uniform).
|
|
757
|
+
// The first two entries reuse buildFullscreenPostInputEntries so the
|
|
758
|
+
// sampleType derivation stays a single SSOT; 'fullscreen-post' is
|
|
759
|
+
// untouched (param-less zero-regression, R-A7).
|
|
760
|
+
return {
|
|
761
|
+
label: 'fullscreen-post-with-params-bgl',
|
|
762
|
+
entries: [
|
|
763
|
+
...buildFullscreenPostInputEntries(spec),
|
|
764
|
+
{
|
|
765
|
+
binding: 2,
|
|
766
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
767
|
+
buffer: { type: 'uniform' },
|
|
768
|
+
},
|
|
769
|
+
],
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
case 'fullscreen-post-with-scene-depth': {
|
|
773
|
+
// plan-strategy D-3: 5-entry BGL for post-process passes that read the
|
|
774
|
+
// camera scene depth. color@0 + sampler@1 reuse buildFullscreenPostInputEntries
|
|
775
|
+
// (float+filtering for color). depthTex@3 uses `sampleType: 'depth'` and
|
|
776
|
+
// `dimension: '2d'`; depthSampler@4 uses `type: 'non-filtering'` (nearest
|
|
777
|
+
// + clamp-to-edge, D-2 — NOT comparison). params@2 is always present
|
|
778
|
+
// (uniform) to avoid a 2x2 kind explosion per D-3.
|
|
779
|
+
return {
|
|
780
|
+
label: 'fullscreen-post-with-scene-depth-bgl',
|
|
781
|
+
entries: [
|
|
782
|
+
...buildFullscreenPostInputEntries(spec),
|
|
783
|
+
{
|
|
784
|
+
binding: 2,
|
|
785
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
786
|
+
buffer: { type: 'uniform' },
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
binding: 3,
|
|
790
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
791
|
+
texture: { sampleType: 'depth', viewDimension: '2d' },
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
binding: 4,
|
|
795
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
796
|
+
sampler: { type: 'non-filtering' },
|
|
797
|
+
},
|
|
798
|
+
],
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
case 'fullscreen-post-with-scene-depth-msaa': {
|
|
802
|
+
return {
|
|
803
|
+
label: 'fullscreen-post-with-scene-depth-msaa-bgl',
|
|
804
|
+
entries: [
|
|
805
|
+
...buildFullscreenPostInputEntries(spec),
|
|
806
|
+
{
|
|
807
|
+
binding: 2,
|
|
808
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
809
|
+
buffer: { type: 'uniform' },
|
|
810
|
+
},
|
|
811
|
+
{
|
|
812
|
+
binding: 3,
|
|
813
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
814
|
+
texture: { sampleType: 'depth', viewDimension: '2d', multisampled: true },
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
binding: 4,
|
|
818
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
819
|
+
sampler: { type: 'non-filtering' },
|
|
820
|
+
},
|
|
821
|
+
],
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
case 'fullscreen-post-with-gbuffer-depth': {
|
|
825
|
+
return {
|
|
826
|
+
label: 'fullscreen-post-with-gbuffer-depth-bgl',
|
|
827
|
+
entries: [
|
|
828
|
+
...buildFullscreenPostInputEntries(spec),
|
|
829
|
+
{
|
|
830
|
+
binding: 2,
|
|
831
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
832
|
+
buffer: { type: 'uniform' },
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
binding: 3,
|
|
836
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
837
|
+
texture: { sampleType: 'depth', viewDimension: '2d' },
|
|
838
|
+
},
|
|
839
|
+
{
|
|
840
|
+
binding: 4,
|
|
841
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
842
|
+
sampler: { type: 'non-filtering' },
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
binding: 5,
|
|
846
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
847
|
+
texture: { sampleType: 'float', viewDimension: '2d' },
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
binding: 6,
|
|
851
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
852
|
+
texture: { sampleType: 'float', viewDimension: '2d' },
|
|
853
|
+
},
|
|
854
|
+
],
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* The shared texture@0 + sampler@1 entries for fullscreen post-process BGLs.
|
|
862
|
+
* sampleType is derived from `spec.attachments` (R3 fix): depth attachments →
|
|
863
|
+
* `'depth'` + `'comparison'` sampler; `'r32float'` → `'unfilterable-float'`;
|
|
864
|
+
* else → `'float'` + `'filtering'`. Both `'fullscreen-post'` and
|
|
865
|
+
* `'fullscreen-post-with-params'` reuse this so the derivation is one SSOT.
|
|
866
|
+
*/
|
|
867
|
+
function buildFullscreenPostInputEntries(spec: PipelineSpec): GPUBindGroupLayoutEntry[] {
|
|
868
|
+
const inputFormat: GPUTextureFormat | undefined =
|
|
869
|
+
spec.attachments.depthFormat ?? spec.attachments.colorFormats[0];
|
|
870
|
+
const sampleType: GPUTextureSampleType =
|
|
871
|
+
inputFormat === 'depth32float' ||
|
|
872
|
+
inputFormat === 'depth24plus' ||
|
|
873
|
+
inputFormat === 'depth24plus-stencil8' ||
|
|
874
|
+
inputFormat === 'depth16unorm'
|
|
875
|
+
? 'depth'
|
|
876
|
+
: inputFormat === 'r32float'
|
|
877
|
+
? 'unfilterable-float'
|
|
878
|
+
: 'float';
|
|
879
|
+
return [
|
|
880
|
+
{
|
|
881
|
+
binding: 0,
|
|
882
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
883
|
+
texture: { sampleType, viewDimension: '2d' },
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
binding: 1,
|
|
887
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
888
|
+
sampler: {
|
|
889
|
+
type: sampleType === 'depth' ? 'comparison' : 'filtering',
|
|
890
|
+
},
|
|
891
|
+
},
|
|
892
|
+
];
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
896
|
+
// passKindPolicyTable — closed map: passKind → attachment shape + default ops
|
|
897
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* Default colour-attachment ops carried by a passKind policy.
|
|
901
|
+
*
|
|
902
|
+
* `clearValue` is `undefined` for `loadOp='load'` policies (no clear value
|
|
903
|
+
* is emitted into the descriptor when the prior contents are loaded).
|
|
904
|
+
*/
|
|
905
|
+
export interface AttachmentColorOps {
|
|
906
|
+
readonly loadOp: 'clear' | 'load';
|
|
907
|
+
readonly storeOp: 'store' | 'discard';
|
|
908
|
+
readonly clearValue: GPUColor | undefined;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Default depth-attachment ops carried by a passKind policy.
|
|
913
|
+
*
|
|
914
|
+
* `stencilLoadOp` / `stencilStoreOp` are absent on the policy itself — the
|
|
915
|
+
* stencil-op gate is auto-derived from `specAttachments.depthFormat` at call
|
|
916
|
+
* time (`'depth24plus-stencil8'` → `'clear'+'discard'`; everything else
|
|
917
|
+
* elides stencil ops). This collapses the R3/R5 stencil-op duplicates that
|
|
918
|
+
* previously lived inline at every forward-pass beginRenderPass call site.
|
|
919
|
+
*/
|
|
920
|
+
export interface AttachmentDepthOps {
|
|
921
|
+
readonly loadOp: 'clear' | 'load';
|
|
922
|
+
readonly storeOp: 'store' | 'discard';
|
|
923
|
+
readonly clearValue: number;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
/**
|
|
927
|
+
* Attachment policy for a single passKind — declares the colour / depth shape
|
|
928
|
+
* the pass produces and the default load/store ops. Per-call-site overrides
|
|
929
|
+
* (skybox vs main forward differing on `colorLoadOp`, sprite-split forward
|
|
930
|
+
* differing on both `colorLoadOp` and `depthLoadOp`) flow through the
|
|
931
|
+
* `options` parameter of {@link buildBeginRenderPassDescriptor}.
|
|
932
|
+
*
|
|
933
|
+
* `shape` discriminator drives which attachment slots the descriptor emits:
|
|
934
|
+
* - `'depth-only'` → empty `colorAttachments[]`, `depthStencilAttachment` set
|
|
935
|
+
* - `'color-only'` → populated `colorAttachments[]`, no `depthStencilAttachment`
|
|
936
|
+
* - `'color-and-depth'` → both
|
|
937
|
+
*/
|
|
938
|
+
export interface PassKindAttachmentPolicy {
|
|
939
|
+
readonly shape: 'depth-only' | 'color-only' | 'color-and-depth';
|
|
940
|
+
readonly defaultColorOps: AttachmentColorOps | undefined;
|
|
941
|
+
readonly defaultDepthOps: AttachmentDepthOps | undefined;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* Closed map of passKind → attachment policy. Covers the 10 attachment shapes
|
|
946
|
+
* the runtime ships (per plan-strategy M4):
|
|
947
|
+
*
|
|
948
|
+
* 1. `'forward'` — main geometry pass: color+depth(+stencil-gated)
|
|
949
|
+
* 2. `'deferred'` — HDRP G-Buffer geometry pass: MRT color+depth
|
|
950
|
+
* 3. `'shadow-caster'` — directional shadow caster: depth-only
|
|
951
|
+
* 4. `'point-shadow-caster'` — HDRP point-shadow caster: depth-only
|
|
952
|
+
* 5. `'skybox'` — fullscreen skybox: color-only clear/store
|
|
953
|
+
* 6. `'tonemap'` — HDR→LDR tonemap fullscreen: color-only clear/store
|
|
954
|
+
* 7. `'bloom-bright'` / `'bloom-blur'` — bloom downsample/blur: color-only
|
|
955
|
+
* clear/store
|
|
956
|
+
* 8. `'bloom-composite'` — bloom add-back: color-only load/store (NOT clear)
|
|
957
|
+
* 9. `'fxaa'` — fullscreen FXAA: color-only clear/store
|
|
958
|
+
* 10. `'post-process'` — generic fullscreen primitive (SSAO, render-graph
|
|
959
|
+
* fullscreen-post-process-pass dispatcher, M2 tonemap pre-warm slot):
|
|
960
|
+
* color-only clear/store
|
|
961
|
+
*
|
|
962
|
+
* Sprite-split forward sub-pass reuses the `'forward'` policy with
|
|
963
|
+
* `options.colorLoadOp='load'` + `options.depthLoadOp='load'`.
|
|
964
|
+
*
|
|
965
|
+
* Stencil-op gate is NOT in this table — it is derived from
|
|
966
|
+
* `specAttachments.depthFormat` inside the helper (depth24plus-stencil8
|
|
967
|
+
* → emit `stencilLoadOp:'clear' / stencilStoreOp:'discard'`).
|
|
968
|
+
*/
|
|
969
|
+
export const passKindPolicyTable: Readonly<Record<string, PassKindAttachmentPolicy>> = {
|
|
970
|
+
forward: {
|
|
971
|
+
shape: 'color-and-depth',
|
|
972
|
+
defaultColorOps: {
|
|
973
|
+
loadOp: 'clear',
|
|
974
|
+
storeOp: 'store',
|
|
975
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
976
|
+
},
|
|
977
|
+
defaultDepthOps: { loadOp: 'clear', storeOp: 'store', clearValue: 1 },
|
|
978
|
+
},
|
|
979
|
+
deferred: {
|
|
980
|
+
shape: 'color-and-depth',
|
|
981
|
+
defaultColorOps: {
|
|
982
|
+
loadOp: 'clear',
|
|
983
|
+
storeOp: 'store',
|
|
984
|
+
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
|
985
|
+
},
|
|
986
|
+
defaultDepthOps: { loadOp: 'clear', storeOp: 'store', clearValue: 1 },
|
|
987
|
+
},
|
|
988
|
+
temporal: {
|
|
989
|
+
shape: 'color-and-depth',
|
|
990
|
+
defaultColorOps: {
|
|
991
|
+
loadOp: 'clear',
|
|
992
|
+
storeOp: 'store',
|
|
993
|
+
clearValue: { r: 0, g: 0, b: -1, a: 1 },
|
|
994
|
+
},
|
|
995
|
+
defaultDepthOps: { loadOp: 'clear', storeOp: 'store', clearValue: 1 },
|
|
996
|
+
},
|
|
997
|
+
'shadow-caster': {
|
|
998
|
+
shape: 'depth-only',
|
|
999
|
+
defaultColorOps: undefined,
|
|
1000
|
+
defaultDepthOps: { loadOp: 'clear', storeOp: 'store', clearValue: 1 },
|
|
1001
|
+
},
|
|
1002
|
+
'point-shadow-caster': {
|
|
1003
|
+
shape: 'depth-only',
|
|
1004
|
+
defaultColorOps: undefined,
|
|
1005
|
+
defaultDepthOps: { loadOp: 'clear', storeOp: 'store', clearValue: 1 },
|
|
1006
|
+
},
|
|
1007
|
+
skybox: {
|
|
1008
|
+
shape: 'color-only',
|
|
1009
|
+
defaultColorOps: {
|
|
1010
|
+
loadOp: 'clear',
|
|
1011
|
+
storeOp: 'store',
|
|
1012
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
1013
|
+
},
|
|
1014
|
+
defaultDepthOps: undefined,
|
|
1015
|
+
},
|
|
1016
|
+
tonemap: {
|
|
1017
|
+
shape: 'color-only',
|
|
1018
|
+
defaultColorOps: {
|
|
1019
|
+
loadOp: 'clear',
|
|
1020
|
+
storeOp: 'store',
|
|
1021
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
1022
|
+
},
|
|
1023
|
+
defaultDepthOps: undefined,
|
|
1024
|
+
},
|
|
1025
|
+
'bloom-bright': {
|
|
1026
|
+
shape: 'color-only',
|
|
1027
|
+
defaultColorOps: {
|
|
1028
|
+
loadOp: 'clear',
|
|
1029
|
+
storeOp: 'store',
|
|
1030
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
1031
|
+
},
|
|
1032
|
+
defaultDepthOps: undefined,
|
|
1033
|
+
},
|
|
1034
|
+
'bloom-blur': {
|
|
1035
|
+
shape: 'color-only',
|
|
1036
|
+
defaultColorOps: {
|
|
1037
|
+
loadOp: 'clear',
|
|
1038
|
+
storeOp: 'store',
|
|
1039
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
1040
|
+
},
|
|
1041
|
+
defaultDepthOps: undefined,
|
|
1042
|
+
},
|
|
1043
|
+
'bloom-composite': {
|
|
1044
|
+
shape: 'color-only',
|
|
1045
|
+
defaultColorOps: {
|
|
1046
|
+
loadOp: 'load',
|
|
1047
|
+
storeOp: 'store',
|
|
1048
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
1049
|
+
},
|
|
1050
|
+
defaultDepthOps: undefined,
|
|
1051
|
+
},
|
|
1052
|
+
fxaa: {
|
|
1053
|
+
shape: 'color-only',
|
|
1054
|
+
defaultColorOps: {
|
|
1055
|
+
loadOp: 'clear',
|
|
1056
|
+
storeOp: 'store',
|
|
1057
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
1058
|
+
},
|
|
1059
|
+
defaultDepthOps: undefined,
|
|
1060
|
+
},
|
|
1061
|
+
'post-process': {
|
|
1062
|
+
shape: 'color-only',
|
|
1063
|
+
defaultColorOps: {
|
|
1064
|
+
loadOp: 'clear',
|
|
1065
|
+
storeOp: 'store',
|
|
1066
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
1067
|
+
},
|
|
1068
|
+
defaultDepthOps: undefined,
|
|
1069
|
+
},
|
|
1070
|
+
};
|
|
1071
|
+
|
|
1072
|
+
/**
|
|
1073
|
+
* Build a `GPURenderPassDescriptor` from spec attachments + resolved views +
|
|
1074
|
+
* a passKind policy lookup.
|
|
1075
|
+
*
|
|
1076
|
+
* The helper is the single SSOT for `device.beginRenderPass(...)` descriptor
|
|
1077
|
+
* shape — every record-stage call site routes through it (plan-strategy M4
|
|
1078
|
+
* AC-06). It dispatches on `passKindPolicyTable[passKind]` to pick the
|
|
1079
|
+
* attachment shape (depth-only / color-only / color-and-depth) and applies
|
|
1080
|
+
* default color/depth load+store ops; per-call overrides (sprite-split's
|
|
1081
|
+
* `loadOp:'load'`, main pass's dynamic `mainColorLoadOp`, skybox's specific
|
|
1082
|
+
* clearColor) flow through `options`.
|
|
1083
|
+
*
|
|
1084
|
+
* Stencil-op gate is auto-derived from `specAttachments.depthFormat`:
|
|
1085
|
+
* - `'depth24plus-stencil8'` → emits `stencilLoadOp:'clear', stencilStoreOp:'discard'`
|
|
1086
|
+
* - any other depth format → omits stencil ops entirely
|
|
1087
|
+
*
|
|
1088
|
+
* This collapses the R3/R5 stencil-op duplicates that previously lived inline
|
|
1089
|
+
* at every forward-pass beginRenderPass site.
|
|
1090
|
+
*
|
|
1091
|
+
* @param specAttachments - the attachments axis from a PipelineSpec
|
|
1092
|
+
* @param viewBindings - resolved texture views: `{ colorViews, depthView?, resolveTargets? }`
|
|
1093
|
+
* @param passKind - one of the keys in {@link passKindPolicyTable}
|
|
1094
|
+
* @param options - per-call ops overrides (loadOp / clearValue / label)
|
|
1095
|
+
* @returns a WebGPU render-pass descriptor
|
|
1096
|
+
* @throws PipelineSpecError(`'unknown-pass-kind'`) when passKind is not registered
|
|
1097
|
+
* @see plan-strategy M4 · requirements AC-06
|
|
1098
|
+
*/
|
|
1099
|
+
export function buildBeginRenderPassDescriptor(
|
|
1100
|
+
specAttachments: PipelineSpec['attachments'],
|
|
1101
|
+
viewBindings: {
|
|
1102
|
+
readonly colorViews: readonly unknown[];
|
|
1103
|
+
readonly resolveTargets?: readonly (unknown | undefined)[];
|
|
1104
|
+
readonly depthView?: unknown;
|
|
1105
|
+
},
|
|
1106
|
+
passKind: string,
|
|
1107
|
+
options?: {
|
|
1108
|
+
readonly colorLoadOp?: 'clear' | 'load';
|
|
1109
|
+
readonly colorStoreOp?: 'store' | 'discard';
|
|
1110
|
+
readonly clearColor?: GPUColor;
|
|
1111
|
+
readonly depthLoadOp?: 'clear' | 'load';
|
|
1112
|
+
readonly depthStoreOp?: 'store' | 'discard';
|
|
1113
|
+
readonly label?: string;
|
|
1114
|
+
},
|
|
1115
|
+
): Record<string, unknown> {
|
|
1116
|
+
const policy = passKindPolicyTable[passKind];
|
|
1117
|
+
if (policy === undefined) {
|
|
1118
|
+
throw new PipelineSpecError({
|
|
1119
|
+
code: 'unknown-pass-kind',
|
|
1120
|
+
detail: { expected: Object.keys(passKindPolicyTable), actual: passKind },
|
|
1121
|
+
hint: `passKind '${passKind}' is not in passKindPolicyTable; register an attachment policy or pick an existing one (e.g. 'post-process' for fullscreen-quad passes)`,
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
const out: Record<string, unknown> = {};
|
|
1126
|
+
if (options?.label !== undefined) {
|
|
1127
|
+
out.label = options.label;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
// Colour attachments: depth-only → empty array; otherwise iterate colorViews
|
|
1131
|
+
// and apply policy default ops + per-call overrides. resolveTargets[i] === undefined
|
|
1132
|
+
// means "no resolve for this slot"; only present slots emit a `resolveTarget`.
|
|
1133
|
+
if (policy.shape === 'depth-only') {
|
|
1134
|
+
out.colorAttachments = [];
|
|
1135
|
+
} else {
|
|
1136
|
+
const colorOps = policy.defaultColorOps;
|
|
1137
|
+
if (colorOps === undefined) {
|
|
1138
|
+
throw new PipelineSpecError({
|
|
1139
|
+
code: 'spec-inconsistent',
|
|
1140
|
+
detail: {
|
|
1141
|
+
reason: 'policy-shape-color-without-colorOps',
|
|
1142
|
+
actual: passKind,
|
|
1143
|
+
},
|
|
1144
|
+
hint: `passKind '${passKind}' has shape='${policy.shape}' but no defaultColorOps; fix passKindPolicyTable entry`,
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
const loadOp = options?.colorLoadOp ?? colorOps.loadOp;
|
|
1148
|
+
const storeOp = options?.colorStoreOp ?? colorOps.storeOp;
|
|
1149
|
+
const clearValue = options?.clearColor ?? colorOps.clearValue;
|
|
1150
|
+
|
|
1151
|
+
out.colorAttachments = viewBindings.colorViews.map((view, i) => {
|
|
1152
|
+
const slot: Record<string, unknown> = {
|
|
1153
|
+
view,
|
|
1154
|
+
loadOp,
|
|
1155
|
+
storeOp,
|
|
1156
|
+
};
|
|
1157
|
+
const resolveTarget = viewBindings.resolveTargets?.[i];
|
|
1158
|
+
if (resolveTarget !== undefined) {
|
|
1159
|
+
slot.resolveTarget = resolveTarget;
|
|
1160
|
+
}
|
|
1161
|
+
// Emit clearValue only when load is 'clear' AND a value is available.
|
|
1162
|
+
if (loadOp === 'clear' && clearValue !== undefined) {
|
|
1163
|
+
slot.clearValue = clearValue;
|
|
1164
|
+
}
|
|
1165
|
+
return slot;
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// Depth-stencil attachment: emitted iff policy declares depth ops AND
|
|
1170
|
+
// the spec carries a depthFormat. Stencil ops auto-derived from format.
|
|
1171
|
+
if (policy.shape !== 'color-only' && policy.defaultDepthOps !== undefined) {
|
|
1172
|
+
const dOps = policy.defaultDepthOps;
|
|
1173
|
+
const depthLoadOp = options?.depthLoadOp ?? dOps.loadOp;
|
|
1174
|
+
const depthStoreOp = options?.depthStoreOp ?? dOps.storeOp;
|
|
1175
|
+
const ds: Record<string, unknown> = {
|
|
1176
|
+
view: viewBindings.depthView,
|
|
1177
|
+
depthLoadOp,
|
|
1178
|
+
depthStoreOp,
|
|
1179
|
+
};
|
|
1180
|
+
if (depthLoadOp === 'clear') {
|
|
1181
|
+
ds.depthClearValue = dOps.clearValue;
|
|
1182
|
+
}
|
|
1183
|
+
// Stencil-op gate: only depth24plus-stencil8 carries a stencil aspect.
|
|
1184
|
+
if (specAttachments.depthFormat === 'depth24plus-stencil8') {
|
|
1185
|
+
ds.stencilClearValue = 0;
|
|
1186
|
+
ds.stencilLoadOp = 'clear';
|
|
1187
|
+
ds.stencilStoreOp = 'discard';
|
|
1188
|
+
}
|
|
1189
|
+
out.depthStencilAttachment = ds;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
return out;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
/**
|
|
1196
|
+
* Dev-mode equality check: two PipelineSpec instances are structurally equal
|
|
1197
|
+
* when every axis field is `===` (shallow compare).
|
|
1198
|
+
*
|
|
1199
|
+
* Not intended for runtime hot paths — use `cacheKeyOf(a) === cacheKeyOf(b)`
|
|
1200
|
+
* for cache-hit checks. This function exists for dev-time assertions
|
|
1201
|
+
* (`assert(specsEqual(specA, specB))`) and unit-test round-trip verification.
|
|
1202
|
+
*
|
|
1203
|
+
* @see plan-strategy §3.2 · requirements AC-02
|
|
1204
|
+
*/
|
|
1205
|
+
export function specsEqual(a: PipelineSpec, b: PipelineSpec): boolean {
|
|
1206
|
+
if (
|
|
1207
|
+
a.shader.id !== b.shader.id ||
|
|
1208
|
+
a.shader.passKind !== b.shader.passKind ||
|
|
1209
|
+
a.shader.variantSet !== b.shader.variantSet ||
|
|
1210
|
+
a.attachments.colorFormats.length !== b.attachments.colorFormats.length ||
|
|
1211
|
+
!a.attachments.colorFormats.every((f, i) => f === b.attachments.colorFormats[i]) ||
|
|
1212
|
+
a.attachments.depthFormat !== b.attachments.depthFormat ||
|
|
1213
|
+
a.attachments.sampleCount !== b.attachments.sampleCount ||
|
|
1214
|
+
a.geometry.topology !== b.geometry.topology ||
|
|
1215
|
+
a.geometry.stripIndexFormat !== b.geometry.stripIndexFormat
|
|
1216
|
+
) {
|
|
1217
|
+
return false;
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
// VertexLayout: same reference or structurally equal keys + byte lengths
|
|
1221
|
+
if (a.geometry.vertexLayout !== b.geometry.vertexLayout) {
|
|
1222
|
+
const aKeys = Object.keys(a.geometry.vertexLayout).sort();
|
|
1223
|
+
const bKeys = Object.keys(b.geometry.vertexLayout).sort();
|
|
1224
|
+
if (aKeys.length !== bKeys.length || !aKeys.every((k, i) => k === bKeys[i])) return false;
|
|
1225
|
+
for (const k of aKeys) {
|
|
1226
|
+
const aBuf = a.geometry.vertexLayout[k as keyof VertexAttributeMap];
|
|
1227
|
+
const bBuf = b.geometry.vertexLayout[k as keyof VertexAttributeMap];
|
|
1228
|
+
if (aBuf === bBuf) continue;
|
|
1229
|
+
if (aBuf === undefined || bBuf === undefined) return false;
|
|
1230
|
+
if ((aBuf as ArrayBuffer).byteLength !== (bBuf as ArrayBuffer).byteLength) return false;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
// RenderState: same reference or JSON-equal
|
|
1235
|
+
if (a.renderState !== b.renderState) {
|
|
1236
|
+
if (a.renderState === undefined || b.renderState === undefined) return false;
|
|
1237
|
+
const aSorted = Object.keys(a.renderState).sort();
|
|
1238
|
+
const bSorted = Object.keys(b.renderState).sort();
|
|
1239
|
+
if (aSorted.length !== bSorted.length || !aSorted.every((k, i) => k === bSorted[i]))
|
|
1240
|
+
return false;
|
|
1241
|
+
for (const k of aSorted) {
|
|
1242
|
+
if (
|
|
1243
|
+
a.renderState[k as keyof MaterialRenderState] !==
|
|
1244
|
+
b.renderState[k as keyof MaterialRenderState]
|
|
1245
|
+
)
|
|
1246
|
+
return false;
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
return true;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
/**
|
|
1254
|
+
* Validate a PipelineSpec before attempting to build.
|
|
1255
|
+
*
|
|
1256
|
+
* Fail-fast checks (charter P5) covering axis mutual-exclusion rules.
|
|
1257
|
+
* Returns `Result<void, PipelineSpecError>` — ok for valid specs,
|
|
1258
|
+
* err with structured code + detail for invalid ones.
|
|
1259
|
+
*
|
|
1260
|
+
* Checks:
|
|
1261
|
+
* 1. `sampleCount=4` with empty `colorFormats` → `'spec-inconsistent'`
|
|
1262
|
+
* 2. Pass kind not in `KNOWN_PASS_KINDS` → `'unknown-pass-kind'`
|
|
1263
|
+
* 3. `depthFormat` undefined but `renderState` implies depth testing →
|
|
1264
|
+
* `'attachment-format-incompatible'`
|
|
1265
|
+
*
|
|
1266
|
+
* @see plan-strategy §3.2 · requirements AC-02 · charter P5
|
|
1267
|
+
*/
|
|
1268
|
+
export function validateSpec(
|
|
1269
|
+
spec: PipelineSpec,
|
|
1270
|
+
):
|
|
1271
|
+
| { ok: true }
|
|
1272
|
+
| { ok: false; code: PipelineSpecErrorCode; detail: Record<string, unknown>; hint?: string } {
|
|
1273
|
+
// Check 1: sampleCount=4 with empty colorFormats is inconsistent —
|
|
1274
|
+
// multisample requires a colour target to resolve to.
|
|
1275
|
+
if (spec.attachments.sampleCount === 4 && spec.attachments.colorFormats.length === 0) {
|
|
1276
|
+
return {
|
|
1277
|
+
ok: false,
|
|
1278
|
+
code: 'spec-inconsistent',
|
|
1279
|
+
detail: { reason: 'sample-count-format-incompatible' },
|
|
1280
|
+
hint: 'sampleCount=4 requires at least one colorFormat; shadow-caster (depth-only) passes should use sampleCount=1',
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// Check 2: unknown pass kind
|
|
1285
|
+
if (!KNOWN_PASS_KINDS.includes(spec.shader.passKind)) {
|
|
1286
|
+
return {
|
|
1287
|
+
ok: false,
|
|
1288
|
+
code: 'unknown-pass-kind',
|
|
1289
|
+
detail: { expected: KNOWN_PASS_KINDS, actual: spec.shader.passKind },
|
|
1290
|
+
hint: `passKind '${spec.shader.passKind}' is not in KNOWN_PASS_KINDS; register custom pass kinds via ShaderRegistry`,
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
// Check 3: depth-testing renderState without a depthFormat
|
|
1295
|
+
if (spec.attachments.depthFormat === undefined && spec.renderState?.depthCompare !== undefined) {
|
|
1296
|
+
return {
|
|
1297
|
+
ok: false,
|
|
1298
|
+
code: 'attachment-format-incompatible',
|
|
1299
|
+
detail: {
|
|
1300
|
+
reason: 'depth-compare-without-depth-format',
|
|
1301
|
+
expected: 'depthFormat must be set when renderState.depthCompare is defined',
|
|
1302
|
+
actual: `depthFormat=${String(spec.attachments.depthFormat)}, depthCompare=${spec.renderState.depthCompare}`,
|
|
1303
|
+
},
|
|
1304
|
+
hint: 'set attachments.depthFormat (e.g. depth24plus-stencil8 or depth32float) when renderState specifies depthCompare',
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
return { ok: true };
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
1312
|
+
// PipelineCache — Map<string, RenderPipeline> container (D-12)
|
|
1313
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* Pipeline cache — Map from cacheKeyOf(spec) to opaque RenderPipeline handle.
|
|
1317
|
+
*
|
|
1318
|
+
* Constructed once at createRenderer boot time; shared across all call sites.
|
|
1319
|
+
* Consumers call `getOrBuildPipeline(spec, deviceProvider, cache)` — the
|
|
1320
|
+
* entrypoint does cache lookup internally; consumers never touch the Map
|
|
1321
|
+
* directly.
|
|
1322
|
+
*
|
|
1323
|
+
* @see plan-strategy D-12 · requirements §3.2
|
|
1324
|
+
*/
|
|
1325
|
+
export type PipelineCache = Map<string, unknown>;
|
|
1326
|
+
|
|
1327
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
1328
|
+
// getOrBuildPipeline — single entrypoint (D-12)
|
|
1329
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* Device factory interface consumed by {@link getOrBuildPipeline}.
|
|
1333
|
+
*
|
|
1334
|
+
* Slim abstraction: only `createRenderPipeline` is needed; the entrypoint
|
|
1335
|
+
* does not depend on the full `RhiDevice` interface so it can be tested
|
|
1336
|
+
* with a mock.
|
|
1337
|
+
*/
|
|
1338
|
+
export interface PipelineDeviceProvider {
|
|
1339
|
+
createRenderPipeline(
|
|
1340
|
+
descriptor: Record<string, unknown>,
|
|
1341
|
+
): { ok: true; value: unknown } | { ok: false; error: unknown };
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* Single entrypoint for obtaining a render pipeline from a spec.
|
|
1346
|
+
*
|
|
1347
|
+
* Cache-hit path: key = cacheKeyOf(spec), returns cached handle immediately.
|
|
1348
|
+
* Cache-miss path: validates spec → builds descriptor → calls device.createRenderPipeline
|
|
1349
|
+
* → caches result → returns handle.
|
|
1350
|
+
* Build failure: throws PipelineSpecError (charter P3 fail-fast, no silent fallback).
|
|
1351
|
+
*
|
|
1352
|
+
* Pure function: same (spec, deviceProvider, cache) always produces the same result.
|
|
1353
|
+
* Boot-time call site: createRenderer wires the real device; record-stage call site
|
|
1354
|
+
* uses ctx.runtime.device (same entrypoint, same signature).
|
|
1355
|
+
*
|
|
1356
|
+
* @param spec - immutable 4-axis pipeline specification
|
|
1357
|
+
* @param deviceProvider - factory with createRenderPipeline method
|
|
1358
|
+
* @param cache - the PipelineCache (shared across boot + record stage)
|
|
1359
|
+
* @returns a RenderPipeline handle (opaque, typed as unknown for M1)
|
|
1360
|
+
* @throws PipelineSpecError on validation failure or build failure
|
|
1361
|
+
* @see plan-strategy D-12 · requirements AC-03 · charter F1
|
|
1362
|
+
*/
|
|
1363
|
+
export function getOrBuildPipeline(
|
|
1364
|
+
spec: PipelineSpec,
|
|
1365
|
+
deviceProvider: PipelineDeviceProvider,
|
|
1366
|
+
cache: PipelineCache,
|
|
1367
|
+
modules?: {
|
|
1368
|
+
vertex: unknown;
|
|
1369
|
+
fragment: unknown;
|
|
1370
|
+
vertexEntryPoint?: string;
|
|
1371
|
+
fragmentEntryPoint?: string;
|
|
1372
|
+
layout?: unknown;
|
|
1373
|
+
},
|
|
1374
|
+
): unknown {
|
|
1375
|
+
const key = cacheKeyOf(spec);
|
|
1376
|
+
|
|
1377
|
+
// Cache hit — return immediately.
|
|
1378
|
+
const cached = cache.get(key);
|
|
1379
|
+
if (cached !== undefined) return cached;
|
|
1380
|
+
|
|
1381
|
+
// Cache miss — validate, build, cache, return.
|
|
1382
|
+
const validation = validateSpec(spec);
|
|
1383
|
+
if (!validation.ok) {
|
|
1384
|
+
throw new PipelineSpecError({
|
|
1385
|
+
code: validation.code,
|
|
1386
|
+
detail: validation.detail,
|
|
1387
|
+
...(validation.hint !== undefined ? { hint: validation.hint } : {}),
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
const descriptor = buildPipelineDescriptor(
|
|
1392
|
+
spec,
|
|
1393
|
+
modules ?? { vertex: undefined, fragment: undefined },
|
|
1394
|
+
);
|
|
1395
|
+
const result = deviceProvider.createRenderPipeline(descriptor);
|
|
1396
|
+
|
|
1397
|
+
if (!result.ok) {
|
|
1398
|
+
throw new PipelineSpecError({
|
|
1399
|
+
code: 'pipeline-build-failed',
|
|
1400
|
+
detail: { cause: result.error },
|
|
1401
|
+
hint: 'device.createRenderPipeline failed for spec; inspect gpuMessage on the error detail',
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
cache.set(key, result.value);
|
|
1406
|
+
return result.value;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
1410
|
+
// SPEC_CONST_TABLE — 12 boot-time pre-warm variants (M1-T5)
|
|
1411
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
1412
|
+
|
|
1413
|
+
const PROCEDURAL_ATTR_LAYOUT: VertexAttributeMap = {
|
|
1414
|
+
position: new Float32Array(0),
|
|
1415
|
+
normal: new Float32Array(0),
|
|
1416
|
+
uv: new Float32Array(0),
|
|
1417
|
+
tangent: new Float32Array(0),
|
|
1418
|
+
};
|
|
1419
|
+
|
|
1420
|
+
const HDR_FORMAT: GPUTextureFormat = 'rgba16float' as unknown as GPUTextureFormat;
|
|
1421
|
+
const DEPTH_DS: GPUTextureFormat = 'depth24plus-stencil8' as unknown as GPUTextureFormat;
|
|
1422
|
+
|
|
1423
|
+
/**
|
|
1424
|
+
* Default LDR view format used when callers ask for the SPEC_CONST table
|
|
1425
|
+
* without an explicit swap-chain format. Kept for the backward-compatible
|
|
1426
|
+
* `SPEC_CONST_TABLE` export consumed by unit tests that exercise the
|
|
1427
|
+
* spec/cache-keying layer in isolation. Runtime callers always pass the
|
|
1428
|
+
* format selected by `selectSwapChainFormat` (Channel 2 BGRA / Channel 3
|
|
1429
|
+
* RGBA / dawn-node RGBA — see bug-20260615 fix-up note in `createRenderer`).
|
|
1430
|
+
*/
|
|
1431
|
+
const DEFAULT_LDR_FORMAT: GPUTextureFormat = 'bgra8unorm-srgb' as unknown as GPUTextureFormat;
|
|
1432
|
+
|
|
1433
|
+
const TRI_GEOMETRY = {
|
|
1434
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
1435
|
+
stripIndexFormat: undefined,
|
|
1436
|
+
vertexLayout: PROCEDURAL_ATTR_LAYOUT,
|
|
1437
|
+
};
|
|
1438
|
+
|
|
1439
|
+
// feat-city-glb multi-UV tiling: the built-in standard PBR shader now declares
|
|
1440
|
+
// UV sets @location(6..12), so naga reflects uvSetCount=8 for it and the URP
|
|
1441
|
+
// record path threads `shaderUvSetCount: 8` into every standard-pbr spec
|
|
1442
|
+
// (createRenderer.ts buildPipelineContext / getMaterialShaderPipeline).
|
|
1443
|
+
// The boot-time prewarm must match on both axes: the PSO vertex layout includes
|
|
1444
|
+
// all declared UV slots, and the cacheKey carries `:uvsc8`. For single-UV
|
|
1445
|
+
// meshes deriveVertexBufferLayout clamp-to-last aliases every missing set onto
|
|
1446
|
+
// the last mesh set (48-byte stride unchanged), so existing geometry remains
|
|
1447
|
+
// byte-stable.
|
|
1448
|
+
// unlit stays on TRI_GEOMETRY (its shader declares only @location(0..3)).
|
|
1449
|
+
const TRI_GEOMETRY_PBR = {
|
|
1450
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
1451
|
+
stripIndexFormat: undefined,
|
|
1452
|
+
vertexLayout: PROCEDURAL_ATTR_LAYOUT,
|
|
1453
|
+
shaderUvSetCount: 8,
|
|
1454
|
+
};
|
|
1455
|
+
|
|
1456
|
+
// M6 fix-up: URP-variant key string for the standard PBR shader. Mirrors the
|
|
1457
|
+
// boot-time variantSet computed at createRenderer.ts step 1b when
|
|
1458
|
+
// `isHdrpActive=false` and `storageBufferCapable=true` (the URP default
|
|
1459
|
+
// surface). The URP record path requests this exact string at every
|
|
1460
|
+
// `getMaterialShaderPipeline` call site, so seeding the table with these
|
|
1461
|
+
// variants keeps the URP cache lookup hot from frame 1 instead of
|
|
1462
|
+
// skip-drawing the first ~1 frames while the async compile resolves.
|
|
1463
|
+
const URP_PBR_VARIANT_SET = 'CLUSTER_FORWARD_AVAILABLE=false+STORAGE_BUFFER_AVAILABLE=true';
|
|
1464
|
+
|
|
1465
|
+
/**
|
|
1466
|
+
* Build the boot-time pre-warm table: 15 standard PipelineSpec variants.
|
|
1467
|
+
*
|
|
1468
|
+
* feat-20260625-refactor-sprite-as-transparent-mesh M3 / w14 (AC-12): the
|
|
1469
|
+
* four `forgeax::default-sprite` entries (LDR S1 + LDR S4 + HDR S1 + HDR S4)
|
|
1470
|
+
* are gone — sprite PSO lands lazily through the generic
|
|
1471
|
+
* per-MaterialShader pipeline cache. Pre-feat count was 19; post-feat 15.
|
|
1472
|
+
*
|
|
1473
|
+
* Matrix:
|
|
1474
|
+
* - 8 base material variants — {unlit, standard-pbr} x {LDR, HDR} x {S1, S4}
|
|
1475
|
+
* - 4 URP-variant standard-pbr — standard-pbr (variantSet=URP_PBR_VARIANT_SET)
|
|
1476
|
+
* x {LDR, HDR} x {S1, S4}; URP record path requests these specs by
|
|
1477
|
+
* `getMaterialShaderPipeline` keying off `cacheKeyOf` so the boot-time
|
|
1478
|
+
* prewarm seeds `materialShaderPipelineCache` and avoids a 1-frame
|
|
1479
|
+
* async-compile skip-draw (M6 fix-up; see render-system-record.ts §URP)
|
|
1480
|
+
* - 3 fullscreen-post — tonemap (LDR S1) + skybox (HDR S1, HDR S4)
|
|
1481
|
+
*
|
|
1482
|
+
* Total: 15. The URP variant is PBR-only because:
|
|
1483
|
+
* - unlit URP record path passes `variantSet=undefined` (the no-variant
|
|
1484
|
+
* boot-default entries already cover it; createRenderer.ts §unlitRsp)
|
|
1485
|
+
* - sprite goes through `getMaterialShaderPipeline('forgeax::sprite', ...)`
|
|
1486
|
+
* lazily at first transparent-LDR-split draw — no boot-time pre-warm.
|
|
1487
|
+
* - HDRP variant (`variantSet=''` or compound `=true` form) is registered
|
|
1488
|
+
* lazily on `installPipeline(hdrpAsset)`, not at boot — adding HDRP
|
|
1489
|
+
* prewarm here would build PSOs against the URP layout (the boot-time
|
|
1490
|
+
* `pbrModule` is the URP variant when `isHdrpActive=false`)
|
|
1491
|
+
*
|
|
1492
|
+
* `ldrViewFormat` parameterises the LDR color attachment format. Callers
|
|
1493
|
+
* pass the runtime-resolved swap-chain view format (Channel 2 typically
|
|
1494
|
+
* `bgra8unorm-srgb`; Channel 3 wgpu-wasm and dawn-node typically
|
|
1495
|
+
* `rgba8unorm-srgb`). Hard-coding `bgra8unorm-srgb` at module load made
|
|
1496
|
+
* the pre-warmed PSOs incompatible with the actual RenderPass color
|
|
1497
|
+
* attachment on Channel 3 / dawn-node, producing whole-commandBuffer
|
|
1498
|
+
* invalid errors on every frame (bug-20260615 fix-up — see
|
|
1499
|
+
* `createRenderer` boot-time pre-warm site).
|
|
1500
|
+
*
|
|
1501
|
+
* Fullscreen passes (fxaa / bloom x 3 / SSAO x 2) are lazy-build — they
|
|
1502
|
+
* use the same getOrBuildPipeline entrypoint but are not in this table.
|
|
1503
|
+
*
|
|
1504
|
+
* @see plan-strategy D-4 · research R-D4 · requirements AC-16
|
|
1505
|
+
* @see bug-20260612-webgpu-canvas-format-prefer-bgra-shipped (same trap shape)
|
|
1506
|
+
*/
|
|
1507
|
+
export function buildSpecConstTable(
|
|
1508
|
+
ldrViewFormat: GPUTextureFormat,
|
|
1509
|
+
): readonly Readonly<PipelineSpec>[] {
|
|
1510
|
+
const TRI_ATTACHMENTS_LDR_S1 = {
|
|
1511
|
+
colorFormats: [ldrViewFormat],
|
|
1512
|
+
depthFormat: DEPTH_DS,
|
|
1513
|
+
sampleCount: 1 as const,
|
|
1514
|
+
};
|
|
1515
|
+
|
|
1516
|
+
const TRI_ATTACHMENTS_LDR_S4 = {
|
|
1517
|
+
colorFormats: [ldrViewFormat],
|
|
1518
|
+
depthFormat: DEPTH_DS,
|
|
1519
|
+
sampleCount: 4 as const,
|
|
1520
|
+
};
|
|
1521
|
+
|
|
1522
|
+
// feat-20260625-refactor-sprite-as-transparent-mesh M3 / w14 (AC-12 / D-7):
|
|
1523
|
+
// SPRITE_ATTACHMENTS_LDR_S1 / S4 (the dedicated non-srgb storage-format
|
|
1524
|
+
// attachments the sprite spec entries consumed) were deleted alongside the
|
|
1525
|
+
// four `forgeax::default-sprite` SPEC_CONST entries. The bgra8unorm storage
|
|
1526
|
+
// format itself is still enforced at the LDR sprite sub-pass attachment
|
|
1527
|
+
// level (the WebGPU pipeline `colorFormats` derive from the actual render
|
|
1528
|
+
// pass attachment view, which is built off `pipelineState.format` =
|
|
1529
|
+
// swap-chain storage format — see `render-system-record.ts` LDR split
|
|
1530
|
+
// beginRenderPass call). The triggering source migrated from the
|
|
1531
|
+
// spec-table id to `material.transparent` (derived by the extract stage
|
|
1532
|
+
// from `passes[0].renderState.blend !== undefined`, the
|
|
1533
|
+
// post-feat-20260626-collapse SSOT; w7 onwards).
|
|
1534
|
+
|
|
1535
|
+
const TRI_ATTACHMENTS_HDR_S1 = {
|
|
1536
|
+
colorFormats: [HDR_FORMAT],
|
|
1537
|
+
depthFormat: DEPTH_DS,
|
|
1538
|
+
sampleCount: 1 as const,
|
|
1539
|
+
};
|
|
1540
|
+
|
|
1541
|
+
const TRI_ATTACHMENTS_HDR_S4 = {
|
|
1542
|
+
colorFormats: [HDR_FORMAT],
|
|
1543
|
+
depthFormat: DEPTH_DS,
|
|
1544
|
+
sampleCount: 4 as const,
|
|
1545
|
+
};
|
|
1546
|
+
|
|
1547
|
+
return [
|
|
1548
|
+
// unlit LDR S1
|
|
1549
|
+
{
|
|
1550
|
+
shader: { id: 'forgeax::default-unlit', passKind: 'forward', variantSet: undefined },
|
|
1551
|
+
attachments: TRI_ATTACHMENTS_LDR_S1,
|
|
1552
|
+
geometry: TRI_GEOMETRY,
|
|
1553
|
+
renderState: undefined,
|
|
1554
|
+
},
|
|
1555
|
+
// unlit LDR S4
|
|
1556
|
+
{
|
|
1557
|
+
shader: { id: 'forgeax::default-unlit', passKind: 'forward', variantSet: undefined },
|
|
1558
|
+
attachments: TRI_ATTACHMENTS_LDR_S4,
|
|
1559
|
+
geometry: TRI_GEOMETRY,
|
|
1560
|
+
renderState: undefined,
|
|
1561
|
+
},
|
|
1562
|
+
// unlit HDR S1
|
|
1563
|
+
{
|
|
1564
|
+
shader: { id: 'forgeax::default-unlit', passKind: 'forward', variantSet: undefined },
|
|
1565
|
+
attachments: TRI_ATTACHMENTS_HDR_S1,
|
|
1566
|
+
geometry: TRI_GEOMETRY,
|
|
1567
|
+
renderState: undefined,
|
|
1568
|
+
},
|
|
1569
|
+
// unlit HDR S4
|
|
1570
|
+
{
|
|
1571
|
+
shader: { id: 'forgeax::default-unlit', passKind: 'forward', variantSet: undefined },
|
|
1572
|
+
attachments: TRI_ATTACHMENTS_HDR_S4,
|
|
1573
|
+
geometry: TRI_GEOMETRY,
|
|
1574
|
+
renderState: undefined,
|
|
1575
|
+
},
|
|
1576
|
+
// standard LDR S1
|
|
1577
|
+
{
|
|
1578
|
+
shader: { id: 'forgeax::default-standard-pbr', passKind: 'forward', variantSet: undefined },
|
|
1579
|
+
attachments: TRI_ATTACHMENTS_LDR_S1,
|
|
1580
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1581
|
+
renderState: undefined,
|
|
1582
|
+
},
|
|
1583
|
+
// standard LDR S4
|
|
1584
|
+
{
|
|
1585
|
+
shader: { id: 'forgeax::default-standard-pbr', passKind: 'forward', variantSet: undefined },
|
|
1586
|
+
attachments: TRI_ATTACHMENTS_LDR_S4,
|
|
1587
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1588
|
+
renderState: undefined,
|
|
1589
|
+
},
|
|
1590
|
+
// standard HDR S1
|
|
1591
|
+
{
|
|
1592
|
+
shader: { id: 'forgeax::default-standard-pbr', passKind: 'forward', variantSet: undefined },
|
|
1593
|
+
attachments: TRI_ATTACHMENTS_HDR_S1,
|
|
1594
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1595
|
+
renderState: undefined,
|
|
1596
|
+
},
|
|
1597
|
+
// standard HDR S4
|
|
1598
|
+
{
|
|
1599
|
+
shader: { id: 'forgeax::default-standard-pbr', passKind: 'forward', variantSet: undefined },
|
|
1600
|
+
attachments: TRI_ATTACHMENTS_HDR_S4,
|
|
1601
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1602
|
+
renderState: undefined,
|
|
1603
|
+
},
|
|
1604
|
+
|
|
1605
|
+
// ── M6 fix-up: URP-variant standard-pbr prewarm ─────────────────────────
|
|
1606
|
+
// URP record path (`getMaterialShaderPipeline`) requests
|
|
1607
|
+
// `variantSet=URP_PBR_VARIANT_SET` for standard-shading entities; pre-M6
|
|
1608
|
+
// the silent `selectStandardFallbackPipeline` shim served the no-variant
|
|
1609
|
+
// boot prewarm during the 1-frame async-compile warmup. With M6's
|
|
1610
|
+
// explicit-failure surface, those URP requests must hit the boot prewarm
|
|
1611
|
+
// by their own variantSet — these 4 entries close that gap.
|
|
1612
|
+
|
|
1613
|
+
// standard PBR URP LDR S1
|
|
1614
|
+
{
|
|
1615
|
+
shader: {
|
|
1616
|
+
id: 'forgeax::default-standard-pbr',
|
|
1617
|
+
passKind: 'forward',
|
|
1618
|
+
variantSet: URP_PBR_VARIANT_SET,
|
|
1619
|
+
},
|
|
1620
|
+
attachments: TRI_ATTACHMENTS_LDR_S1,
|
|
1621
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1622
|
+
renderState: undefined,
|
|
1623
|
+
},
|
|
1624
|
+
// standard PBR URP LDR S4
|
|
1625
|
+
{
|
|
1626
|
+
shader: {
|
|
1627
|
+
id: 'forgeax::default-standard-pbr',
|
|
1628
|
+
passKind: 'forward',
|
|
1629
|
+
variantSet: URP_PBR_VARIANT_SET,
|
|
1630
|
+
},
|
|
1631
|
+
attachments: TRI_ATTACHMENTS_LDR_S4,
|
|
1632
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1633
|
+
renderState: undefined,
|
|
1634
|
+
},
|
|
1635
|
+
// standard PBR URP HDR S1
|
|
1636
|
+
{
|
|
1637
|
+
shader: {
|
|
1638
|
+
id: 'forgeax::default-standard-pbr',
|
|
1639
|
+
passKind: 'forward',
|
|
1640
|
+
variantSet: URP_PBR_VARIANT_SET,
|
|
1641
|
+
},
|
|
1642
|
+
attachments: TRI_ATTACHMENTS_HDR_S1,
|
|
1643
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1644
|
+
renderState: undefined,
|
|
1645
|
+
},
|
|
1646
|
+
// standard PBR URP HDR S4
|
|
1647
|
+
{
|
|
1648
|
+
shader: {
|
|
1649
|
+
id: 'forgeax::default-standard-pbr',
|
|
1650
|
+
passKind: 'forward',
|
|
1651
|
+
variantSet: URP_PBR_VARIANT_SET,
|
|
1652
|
+
},
|
|
1653
|
+
attachments: TRI_ATTACHMENTS_HDR_S4,
|
|
1654
|
+
geometry: TRI_GEOMETRY_PBR,
|
|
1655
|
+
renderState: undefined,
|
|
1656
|
+
},
|
|
1657
|
+
|
|
1658
|
+
// feat-20260625-refactor-sprite-as-transparent-mesh M3 / w14 (AC-12 / D-7):
|
|
1659
|
+
// the four `forgeax::default-sprite` boot-time pre-warm entries (LDR S1
|
|
1660
|
+
// + LDR S4 + HDR S1 + HDR S4) are gone. Sprite PSO lands lazily through
|
|
1661
|
+
// the generic per-MaterialShader pipeline cache keyed on
|
|
1662
|
+
// `forgeax::sprite` + premultiplied-alpha renderState; SPEC_CONST_TABLE
|
|
1663
|
+
// shrinks from 19 to 15 entries (-4 boot-time PSOs).
|
|
1664
|
+
|
|
1665
|
+
// ── M2-T4: fullscreen-post boot-time pre-warm (tonemap + skybox) ──────────
|
|
1666
|
+
//
|
|
1667
|
+
// Tonemap (LDR S1): fullscreen triangle writes to swap-chain LDR view format
|
|
1668
|
+
// (parameterised — `ldrViewFormat`; see buildSpecConstTable jsdoc + bug-20260615).
|
|
1669
|
+
// Skybox (HDR S1 + S4): fullscreen triangle writes to rgba16float; MSAA variant
|
|
1670
|
+
// has sampleCount=4. Both use empty vertexLayout (fullscreen triangle, no
|
|
1671
|
+
// attributes) and cullMode='none' (forward cull for fullscreen-quad passthrough).
|
|
1672
|
+
//
|
|
1673
|
+
// Shadow-probe / fxaa / bloom 4-stage / SSAO 2-stage are lazy-build — not in
|
|
1674
|
+
// SPEC_CONST_TABLE (R-D4 decision: only entries that are always-present on
|
|
1675
|
+
// every boot).
|
|
1676
|
+
|
|
1677
|
+
// tonemap LDR S1 (writes to runtime-resolved swap-chain LDR view format)
|
|
1678
|
+
{
|
|
1679
|
+
shader: { id: 'forgeax::post::tonemap', passKind: 'post-process', variantSet: undefined },
|
|
1680
|
+
attachments: {
|
|
1681
|
+
colorFormats: [ldrViewFormat],
|
|
1682
|
+
depthFormat: undefined,
|
|
1683
|
+
sampleCount: 1 as const,
|
|
1684
|
+
},
|
|
1685
|
+
geometry: {
|
|
1686
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
1687
|
+
stripIndexFormat: undefined,
|
|
1688
|
+
vertexLayout: {},
|
|
1689
|
+
},
|
|
1690
|
+
renderState: {
|
|
1691
|
+
cullMode: 'none',
|
|
1692
|
+
},
|
|
1693
|
+
},
|
|
1694
|
+
|
|
1695
|
+
// skybox HDR S1 (writes to rgba16float, no depth)
|
|
1696
|
+
{
|
|
1697
|
+
shader: { id: 'forgeax::skybox::cube', passKind: 'skybox', variantSet: undefined },
|
|
1698
|
+
attachments: {
|
|
1699
|
+
colorFormats: [HDR_FORMAT],
|
|
1700
|
+
depthFormat: undefined,
|
|
1701
|
+
sampleCount: 1 as const,
|
|
1702
|
+
},
|
|
1703
|
+
geometry: {
|
|
1704
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
1705
|
+
stripIndexFormat: undefined,
|
|
1706
|
+
vertexLayout: {},
|
|
1707
|
+
},
|
|
1708
|
+
renderState: {
|
|
1709
|
+
cullMode: 'none',
|
|
1710
|
+
},
|
|
1711
|
+
},
|
|
1712
|
+
|
|
1713
|
+
// skybox HDR S4 (MSAA variant)
|
|
1714
|
+
{
|
|
1715
|
+
shader: { id: 'forgeax::skybox::cube', passKind: 'skybox', variantSet: undefined },
|
|
1716
|
+
attachments: {
|
|
1717
|
+
colorFormats: [HDR_FORMAT],
|
|
1718
|
+
depthFormat: undefined,
|
|
1719
|
+
sampleCount: 4 as const,
|
|
1720
|
+
},
|
|
1721
|
+
geometry: {
|
|
1722
|
+
topology: 'triangle-list' as PrimitiveTopology,
|
|
1723
|
+
stripIndexFormat: undefined,
|
|
1724
|
+
vertexLayout: {},
|
|
1725
|
+
},
|
|
1726
|
+
renderState: {
|
|
1727
|
+
cullMode: 'none',
|
|
1728
|
+
},
|
|
1729
|
+
},
|
|
1730
|
+
];
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
/**
|
|
1734
|
+
* Derive the material-only pre-warm table for a native linear-LDR target.
|
|
1735
|
+
*
|
|
1736
|
+
* The regular SPEC_CONST table targets the swap-chain view, while the
|
|
1737
|
+
* tonemap=none path records geometry directly into the graph-owned
|
|
1738
|
+
* `rgba16float` target. Keep that second attachment matrix derived from the
|
|
1739
|
+
* same material specs so the first frame does not depend on an asynchronous
|
|
1740
|
+
* lazy PSO build.
|
|
1741
|
+
*/
|
|
1742
|
+
export function buildLinearLdrMaterialSpecTable(
|
|
1743
|
+
ldrViewFormat: GPUTextureFormat,
|
|
1744
|
+
): readonly Readonly<PipelineSpec>[] {
|
|
1745
|
+
return buildSpecConstTable(ldrViewFormat)
|
|
1746
|
+
.filter(
|
|
1747
|
+
(spec) =>
|
|
1748
|
+
spec.shader.passKind === 'forward' && spec.attachments.colorFormats[0] === ldrViewFormat,
|
|
1749
|
+
)
|
|
1750
|
+
.map((spec) => ({
|
|
1751
|
+
...spec,
|
|
1752
|
+
attachments: {
|
|
1753
|
+
...spec.attachments,
|
|
1754
|
+
colorFormats: [HDR_FORMAT],
|
|
1755
|
+
},
|
|
1756
|
+
}));
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
/**
|
|
1760
|
+
* Backward-compatible SPEC_CONST_TABLE — the table built with the default
|
|
1761
|
+
* LDR view format (`bgra8unorm-srgb`). Unit tests that exercise the
|
|
1762
|
+
* spec/cache-keying layer in isolation import this directly. Runtime
|
|
1763
|
+
* callers MUST call `buildSpecConstTable(swapChainFormats.view)` instead
|
|
1764
|
+
* so the pre-warmed PSO color format matches the actual RenderPass color
|
|
1765
|
+
* attachment on every backend (bug-20260615 fix-up).
|
|
1766
|
+
*/
|
|
1767
|
+
export const SPEC_CONST_TABLE: readonly Readonly<PipelineSpec>[] =
|
|
1768
|
+
buildSpecConstTable(DEFAULT_LDR_FORMAT);
|