@forgeax/engine-render 0.0.0-dev.8d955ade1c79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +647 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/__tests__/authoring-path.unit.test.d.ts +2 -0
- package/dist/__tests__/authoring-path.unit.test.d.ts.map +1 -0
- package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts +2 -0
- package/dist/__tests__/backend-selection-rhi-capture.test-d.d.ts.map +1 -0
- package/dist/__tests__/callback-inference.test-d.d.ts +2 -0
- package/dist/__tests__/callback-inference.test-d.d.ts.map +1 -0
- package/dist/__tests__/cluster-binner.test.d.ts +2 -0
- package/dist/__tests__/cluster-binner.test.d.ts.map +1 -0
- package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/cluster-grid-default-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/construct-renderer-identity.unit.test.d.ts +2 -0
- package/dist/__tests__/construct-renderer-identity.unit.test.d.ts.map +1 -0
- package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts +2 -0
- package/dist/__tests__/device-scope-lifecycle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts +2 -0
- package/dist/__tests__/device-scope-stale-matrix.unit.test.d.ts.map +1 -0
- package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts +2 -0
- package/dist/__tests__/direct-extract-consumer-contract.test-d.d.ts.map +1 -0
- package/dist/__tests__/direct-light-snapshot.unit.test.d.ts +2 -0
- package/dist/__tests__/direct-light-snapshot.unit.test.d.ts.map +1 -0
- package/dist/__tests__/factory-contract.integration.test.d.ts +2 -0
- package/dist/__tests__/factory-contract.integration.test.d.ts.map +1 -0
- package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/fallback-row-stride-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/frame-observation.contract.test.d.ts +2 -0
- package/dist/__tests__/frame-observation.contract.test.d.ts.map +1 -0
- package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/fullscreen-feature-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts +2 -0
- package/dist/__tests__/glyph-text-layout-recovery.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts +6 -0
- package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-indirect-raster.browser.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-indirect-raster.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-production.integration.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-production.integration.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-scaling.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts +18 -0
- package/dist/__tests__/gpu-driven-view-gpu-evidence.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-view-graph.integration.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view-reference.d.ts +15 -0
- package/dist/__tests__/gpu-driven-view-reference.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view.browser.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-view.browser.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view.dawn.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-view.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-driven-view.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-driven-view.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-resource-store-stride.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts +7 -0
- package/dist/__tests__/gpu-scene-render-graph-gpu.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene-render-graph.browser.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene-render-graph.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene-schema.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene-schema.unit.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene.dawn.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/gpu-scene.unit.test.d.ts +2 -0
- package/dist/__tests__/gpu-scene.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts +2 -0
- package/dist/__tests__/ibl/face-uniforms.unit.test.d.ts.map +1 -0
- package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts +2 -0
- package/dist/__tests__/infinite-grid-no-vertex-probe.unit.test.d.ts.map +1 -0
- package/dist/__tests__/injection-kind-owner.test-d.d.ts +2 -0
- package/dist/__tests__/injection-kind-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts +2 -0
- package/dist/__tests__/ktx2-basis-gpu-consumer.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/light-buffer-layout.unit.test.d.ts +2 -0
- package/dist/__tests__/light-buffer-layout.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-contract-inventory.unit.test.d.ts +2 -0
- package/dist/__tests__/material-contract-inventory.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-cooked-projection.unit.test.d.ts +2 -0
- package/dist/__tests__/material-cooked-projection.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts +2 -0
- package/dist/__tests__/material-snapshot-mutation.integration.test.d.ts.map +1 -0
- package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts +2 -0
- package/dist/__tests__/material-static-dynamic-route.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-stride-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/material-stride-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-buffer-usage-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-material-bindings.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-material-bindings.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-stride-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-stride-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts +2 -0
- package/dist/__tests__/morph-culling-reentry.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts +2 -0
- package/dist/__tests__/morph-feature-gpu-work.integration.test.d.ts.map +1 -0
- package/dist/__tests__/morph-feature-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/morph-feature-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/morph-visual-evidence.integration.test.d.ts +2 -0
- package/dist/__tests__/morph-visual-evidence.integration.test.d.ts.map +1 -0
- package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/nineslice-handle-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts +2 -0
- package/dist/__tests__/post-process-error-policy-owner.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts +2 -0
- package/dist/__tests__/prepared-buffer-kind-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-capability.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-generation.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-lifecycle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-pipeline-warmup.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-resolver.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-snapshot.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-store.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-store.unit.test.d.ts.map +1 -0
- package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts +2 -0
- package/dist/__tests__/prepared-graphics-validation.unit.test.d.ts.map +1 -0
- package/dist/__tests__/profiler-default-off.test.d.ts +2 -0
- package/dist/__tests__/profiler-default-off.test.d.ts.map +1 -0
- package/dist/__tests__/profiler-phase-catalog.test.d.ts +2 -0
- package/dist/__tests__/profiler-phase-catalog.test.d.ts.map +1 -0
- package/dist/__tests__/profiler-phase-integration.test.d.ts +2 -0
- package/dist/__tests__/profiler-phase-integration.test.d.ts.map +1 -0
- package/dist/__tests__/profiler-phase-token.test.d.ts +2 -0
- package/dist/__tests__/profiler-phase-token.test.d.ts.map +1 -0
- package/dist/__tests__/public-surface.test-d.d.ts +2 -0
- package/dist/__tests__/public-surface.test-d.d.ts.map +1 -0
- package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts +2 -0
- package/dist/__tests__/recover-error-policy-owner.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-error-code-owner.test-d.d.ts +2 -0
- package/dist/__tests__/render-error-code-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-error-detail-ssot.test-d.d.ts +2 -0
- package/dist/__tests__/render-error-detail-ssot.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts +2 -0
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-assembly.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-assembly.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-context.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-context.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-contract.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-contract.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-diagnostics.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-docs.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-docs.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-errors.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-errors.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts +2 -0
- package/dist/__tests__/render-feature-gpu-work.integration.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-plan.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-plan.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-diagnostics.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-errors.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics-docs.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics-isolation.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics-negative.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-prepared-graphics.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-public-surface.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-public-surface.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-retry.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-retry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-scheduling.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-scheduling.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-stage-failed-policy-owner.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-stage-fault-recovery.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-visibility-context.test-d.d.ts +2 -0
- package/dist/__tests__/render-feature-visibility-context.test-d.d.ts.map +1 -0
- package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-visibility-context.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-feature-zero-work.unit.test.d.ts +2 -0
- package/dist/__tests__/render-feature-zero-work.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-compute-raster-gpu.d.ts +7 -0
- package/dist/__tests__/render-graph-compute-raster-gpu.d.ts.map +1 -0
- package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts +2 -0
- package/dist/__tests__/render-graph-compute-raster.browser.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts +2 -0
- package/dist/__tests__/render-graph-compute-raster.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-hzb-gpu.d.ts +7 -0
- package/dist/__tests__/render-graph-hzb-gpu.d.ts.map +1 -0
- package/dist/__tests__/render-graph-hzb.browser.test.d.ts +2 -0
- package/dist/__tests__/render-graph-hzb.browser.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-hzb.dawn.test.d.ts +2 -0
- package/dist/__tests__/render-graph-hzb.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-primitives.unit.test.d.ts +2 -0
- package/dist/__tests__/render-graph-primitives.unit.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts +12 -0
- package/dist/__tests__/render-graph-storage-indirect-gpu.d.ts.map +1 -0
- package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts +2 -0
- package/dist/__tests__/render-graph-storage-indirect.browser.test.d.ts.map +1 -0
- package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts +2 -0
- package/dist/__tests__/render-graph-storage-indirect.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/render-scene-projection.unit.test.d.ts +2 -0
- package/dist/__tests__/render-scene-projection.unit.test.d.ts.map +1 -0
- package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/renderer-factory-material-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/renderer-lifecycle.integration.test.d.ts +2 -0
- package/dist/__tests__/renderer-lifecycle.integration.test.d.ts.map +1 -0
- package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts +2 -0
- package/dist/__tests__/rhi-backend-package-boundary.unit.test.d.ts.map +1 -0
- package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts +2 -0
- package/dist/__tests__/scriptable-pack-consumer.test-d.d.ts.map +1 -0
- package/dist/__tests__/shader-stage-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/shader-stage-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ssao-config.unit.test.d.ts +2 -0
- package/dist/__tests__/ssao-config.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/ssao-kernel-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts +2 -0
- package/dist/__tests__/standard-clustered-pipeline.unit.test.d.ts.map +1 -0
- package/dist/__tests__/standard-descriptors.test-d.d.ts +2 -0
- package/dist/__tests__/standard-descriptors.test-d.d.ts.map +1 -0
- package/dist/__tests__/standard-pipeline.dawn.test.d.ts +2 -0
- package/dist/__tests__/standard-pipeline.dawn.test.d.ts.map +1 -0
- package/dist/__tests__/standard-pipeline.integration.test.d.ts +2 -0
- package/dist/__tests__/standard-pipeline.integration.test.d.ts.map +1 -0
- package/dist/__tests__/standard-profile-oracle.unit.test.d.ts +2 -0
- package/dist/__tests__/standard-profile-oracle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/surface-configuration.unit.test.d.ts +2 -0
- package/dist/__tests__/surface-configuration.unit.test.d.ts.map +1 -0
- package/dist/__tests__/texture-usage-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/texture-usage-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts +2 -0
- package/dist/__tests__/typed-pipeline-topology.unit.test.d.ts.map +1 -0
- package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts +2 -0
- package/dist/__tests__/urp-pipeline-targets.unit.test.d.ts.map +1 -0
- package/dist/__tests__/urp-pipeline.unit.test.d.ts +2 -0
- package/dist/__tests__/urp-pipeline.unit.test.d.ts.map +1 -0
- package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts +2 -0
- package/dist/__tests__/vertex-color-pipeline.unit.test.d.ts.map +1 -0
- package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts +2 -0
- package/dist/__tests__/vertex-layout-consumer.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-diagnostics.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-diagnostics.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-extract.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-extract.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-extract.perf.test.d.ts +2 -0
- package/dist/__tests__/visibility-extract.perf.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-feature-dedup.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-hidden-report.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-hidden-report.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-instances.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-instances.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-multi-world.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-multi-world.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts +2 -0
- package/dist/__tests__/visibility-producer-matrix.integration.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-producer-matrix.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-public-surface.test-d.d.ts +2 -0
- package/dist/__tests__/visibility-public-surface.test-d.d.ts.map +1 -0
- package/dist/__tests__/visibility-resolver.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-resolver.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-resource-short-circuit.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-snapshot-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/vocabulary.unit.test.d.ts +2 -0
- package/dist/__tests__/vocabulary.unit.test.d.ts.map +1 -0
- package/dist/assembly/backend-contract.d.ts +37 -0
- package/dist/assembly/backend-contract.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +207 -0
- package/dist/assembly/factory.d.ts.map +1 -0
- package/dist/assembly/host-contract.d.ts +84 -0
- package/dist/assembly/host-contract.d.ts.map +1 -0
- package/dist/assembly/material/assembly.d.ts +21 -0
- package/dist/assembly/material/assembly.d.ts.map +1 -0
- package/dist/assembly/material/pipeline-projection.d.ts +30 -0
- package/dist/assembly/material/pipeline-projection.d.ts.map +1 -0
- package/dist/assets/asset-decoders.d.ts +5 -0
- package/dist/assets/asset-decoders.d.ts.map +1 -0
- package/dist/assets/render-asset-port.d.ts +17 -0
- package/dist/assets/render-asset-port.d.ts.map +1 -0
- package/dist/assets/resolve-render-asset.d.ts +6 -0
- package/dist/assets/resolve-render-asset.d.ts.map +1 -0
- package/dist/authoring.d.ts +12 -0
- package/dist/authoring.d.ts.map +1 -0
- package/dist/authoring.mjs +27 -0
- package/dist/authoring.mjs.map +1 -0
- package/dist/chunk-CQXZC5XI.mjs +182 -0
- package/dist/chunk-CQXZC5XI.mjs.map +1 -0
- package/dist/chunk-HCOGPHKS.mjs +93 -0
- package/dist/chunk-HCOGPHKS.mjs.map +1 -0
- package/dist/chunk-YEJIUW7D.mjs +1152 -0
- package/dist/chunk-YEJIUW7D.mjs.map +1 -0
- package/dist/cluster-binner.d.ts +152 -0
- package/dist/cluster-binner.d.ts.map +1 -0
- package/dist/components/__tests__/points-lines-admission.unit.test.d.ts +2 -0
- package/dist/components/__tests__/points-lines-admission.unit.test.d.ts.map +1 -0
- package/dist/components/__tests__/points-lines-schema.unit.test.d.ts +2 -0
- package/dist/components/__tests__/points-lines-schema.unit.test.d.ts.map +1 -0
- package/dist/components/__tests__/schema-contract.unit.test.d.ts +2 -0
- package/dist/components/__tests__/schema-contract.unit.test.d.ts.map +1 -0
- package/dist/components/__tests__/schema-parity.unit.test.d.ts +2 -0
- package/dist/components/__tests__/schema-parity.unit.test.d.ts.map +1 -0
- package/dist/components/__tests__/visibility-schema.unit.test.d.ts +2 -0
- package/dist/components/__tests__/visibility-schema.unit.test.d.ts.map +1 -0
- package/dist/components/camera.d.ts +311 -0
- package/dist/components/camera.d.ts.map +1 -0
- package/dist/components/directional-light.d.ts +76 -0
- package/dist/components/directional-light.d.ts.map +1 -0
- package/dist/components/glyph-text.d.ts +26 -0
- package/dist/components/glyph-text.d.ts.map +1 -0
- package/dist/components/index.d.ts +24 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/instances.d.ts +41 -0
- package/dist/components/instances.d.ts.map +1 -0
- package/dist/components/layer.d.ts +34 -0
- package/dist/components/layer.d.ts.map +1 -0
- package/dist/components/light-helpers.d.ts +53 -0
- package/dist/components/light-helpers.d.ts.map +1 -0
- package/dist/components/lines.d.ts +5 -0
- package/dist/components/lines.d.ts.map +1 -0
- package/dist/components/mesh-filter.d.ts +24 -0
- package/dist/components/mesh-filter.d.ts.map +1 -0
- package/dist/components/mesh-renderer.d.ts +33 -0
- package/dist/components/mesh-renderer.d.ts.map +1 -0
- package/dist/components/point-light-shadow.d.ts +27 -0
- package/dist/components/point-light-shadow.d.ts.map +1 -0
- package/dist/components/point-light.d.ts +35 -0
- package/dist/components/point-light.d.ts.map +1 -0
- package/dist/components/points.d.ts +15 -0
- package/dist/components/points.d.ts.map +1 -0
- package/dist/components/post-process-params.d.ts +5 -0
- package/dist/components/post-process-params.d.ts.map +1 -0
- package/dist/components/scene-instance.d.ts +140 -0
- package/dist/components/scene-instance.d.ts.map +1 -0
- package/dist/components/skybox-background.d.ts +56 -0
- package/dist/components/skybox-background.d.ts.map +1 -0
- package/dist/components/skylight.d.ts +55 -0
- package/dist/components/skylight.d.ts.map +1 -0
- package/dist/components/sort-key.d.ts +44 -0
- package/dist/components/sort-key.d.ts.map +1 -0
- package/dist/components/spot-light.d.ts +81 -0
- package/dist/components/spot-light.d.ts.map +1 -0
- package/dist/components/sprite-animation.d.ts +74 -0
- package/dist/components/sprite-animation.d.ts.map +1 -0
- package/dist/components/sprite-instances.d.ts +51 -0
- package/dist/components/sprite-instances.d.ts.map +1 -0
- package/dist/components/sprite-playback-mode.d.ts +42 -0
- package/dist/components/sprite-playback-mode.d.ts.map +1 -0
- package/dist/components/sprite-region-override.d.ts +46 -0
- package/dist/components/sprite-region-override.d.ts.map +1 -0
- package/dist/components/tile-layer.d.ts +106 -0
- package/dist/components/tile-layer.d.ts.map +1 -0
- package/dist/components/tilemap.d.ts +25 -0
- package/dist/components/tilemap.d.ts.map +1 -0
- package/dist/components/visibility.d.ts +22 -0
- package/dist/components/visibility.d.ts.map +1 -0
- package/dist/construct-renderer.d.ts +19 -0
- package/dist/construct-renderer.d.ts.map +1 -0
- package/dist/construct-renderer.mjs +27462 -0
- package/dist/construct-renderer.mjs.map +1 -0
- package/dist/debug-draw-glue.d.ts +5 -0
- package/dist/debug-draw-glue.d.ts.map +1 -0
- package/dist/device/device-scope.d.ts +83 -0
- package/dist/device/device-scope.d.ts.map +1 -0
- package/dist/device/gpu-residency.d.ts +337 -0
- package/dist/device/gpu-residency.d.ts.map +1 -0
- package/dist/device/resource-types.d.ts +8 -0
- package/dist/device/resource-types.d.ts.map +1 -0
- package/dist/engine-metrics.d.ts +23 -0
- package/dist/engine-metrics.d.ts.map +1 -0
- package/dist/errors/ecs-validation.d.ts +3 -0
- package/dist/errors/ecs-validation.d.ts.map +1 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/recover.d.ts +105 -0
- package/dist/errors/recover.d.ts.map +1 -0
- package/dist/errors/render.d.ts +705 -0
- package/dist/errors/render.d.ts.map +1 -0
- package/dist/extract/visibility.d.ts +26 -0
- package/dist/extract/visibility.d.ts.map +1 -0
- package/dist/features/fullscreen.d.ts +19 -0
- package/dist/features/fullscreen.d.ts.map +1 -0
- package/dist/features/host.d.ts +106 -0
- package/dist/features/host.d.ts.map +1 -0
- package/dist/features/morph/morph-feature.d.ts +79 -0
- package/dist/features/morph/morph-feature.d.ts.map +1 -0
- package/dist/features/plan.d.ts +182 -0
- package/dist/features/plan.d.ts.map +1 -0
- package/dist/features/prepared-gpu-work.d.ts +117 -0
- package/dist/features/prepared-gpu-work.d.ts.map +1 -0
- package/dist/features/prepared-graphics-store.d.ts +66 -0
- package/dist/features/prepared-graphics-store.d.ts.map +1 -0
- package/dist/features/prepared-graphics.d.ts +215 -0
- package/dist/features/prepared-graphics.d.ts.map +1 -0
- package/dist/features/render-graph-compute.d.ts +13 -0
- package/dist/features/render-graph-compute.d.ts.map +1 -0
- package/dist/features/render-graph-contribution.d.ts +12 -0
- package/dist/features/render-graph-contribution.d.ts.map +1 -0
- package/dist/features/render-graph-raster.d.ts +38 -0
- package/dist/features/render-graph-raster.d.ts.map +1 -0
- package/dist/features/render-graph-resources.d.ts +11 -0
- package/dist/features/render-graph-resources.d.ts.map +1 -0
- package/dist/features/targets.d.ts +32 -0
- package/dist/features/targets.d.ts.map +1 -0
- package/dist/features/types.d.ts +68 -0
- package/dist/features/types.d.ts.map +1 -0
- package/dist/features/vocabulary.d.ts +14 -0
- package/dist/features/vocabulary.d.ts.map +1 -0
- package/dist/fullscreen-post-process-pass.d.ts +157 -0
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -0
- package/dist/glyph-text-layout-system.d.ts +19 -0
- package/dist/glyph-text-layout-system.d.ts.map +1 -0
- package/dist/gpu-driven/batch-topology.d.ts +55 -0
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -0
- package/dist/gpu-driven/production-raster.d.ts +51 -0
- package/dist/gpu-driven/production-raster.d.ts.map +1 -0
- package/dist/gpu-driven/view-gpu.d.ts +85 -0
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -0
- package/dist/gpu-resource.d.ts +73 -0
- package/dist/gpu-resource.d.ts.map +1 -0
- package/dist/gpu-scene-schema.d.ts +78 -0
- package/dist/gpu-scene-schema.d.ts.map +1 -0
- package/dist/gpu-scene.d.ts +55 -0
- package/dist/gpu-scene.d.ts.map +1 -0
- package/dist/gpu-stage.d.ts +4 -0
- package/dist/gpu-stage.d.ts.map +1 -0
- package/dist/gpu-texture-usage.d.ts +6 -0
- package/dist/gpu-texture-usage.d.ts.map +1 -0
- package/dist/gpu-usage.d.ts +9 -0
- package/dist/gpu-usage.d.ts.map +1 -0
- package/dist/hdrp-buffers.d.ts +163 -0
- package/dist/hdrp-buffers.d.ts.map +1 -0
- package/dist/ibl/IblPipelineCache.d.ts +168 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -0
- package/dist/ibl/skylight-bind-group.d.ts +130 -0
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +169 -0
- package/dist/index.mjs.map +1 -0
- package/dist/inspection-types.d.ts +72 -0
- package/dist/inspection-types.d.ts.map +1 -0
- package/dist/instance-buffer-cache.d.ts +56 -0
- package/dist/instance-buffer-cache.d.ts.map +1 -0
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.mjs +3 -0
- package/dist/internal.mjs.map +1 -0
- package/dist/lifecycle.d.ts +62 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/light-buffer-layout.d.ts +164 -0
- package/dist/light-buffer-layout.d.ts.map +1 -0
- package/dist/materials.d.ts +47 -0
- package/dist/materials.d.ts.map +1 -0
- package/dist/mesh-material-bindings.d.ts +43 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -0
- package/dist/pbr-pipeline.d.ts +301 -0
- package/dist/pbr-pipeline.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts +5 -0
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts +31 -0
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -0
- package/dist/pipeline/standard-profile.d.ts +40 -0
- package/dist/pipeline/standard-profile.d.ts.map +1 -0
- package/dist/pipeline-builder.d.ts +122 -0
- package/dist/pipeline-builder.d.ts.map +1 -0
- package/dist/pipeline-spec-types.d.ts +24 -0
- package/dist/pipeline-spec-types.d.ts.map +1 -0
- package/dist/pipeline-spec.d.ts +367 -0
- package/dist/pipeline-spec.d.ts.map +1 -0
- package/dist/plugin.d.ts +4 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/points-lines/__tests__/bounds.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/bounds.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts +2 -0
- package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/inspection.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/inspection.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts +2 -0
- package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/points-lines.bench.d.ts +2 -0
- package/dist/points-lines/__tests__/points-lines.bench.d.ts.map +1 -0
- package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts +2 -0
- package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/snapshot.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/snapshot.unit.test.d.ts.map +1 -0
- package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts +2 -0
- package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts.map +1 -0
- package/dist/points-lines/admission.d.ts +36 -0
- package/dist/points-lines/admission.d.ts.map +1 -0
- package/dist/points-lines/bounds.d.ts +8 -0
- package/dist/points-lines/bounds.d.ts.map +1 -0
- package/dist/points-lines/expansion-cache.d.ts +28 -0
- package/dist/points-lines/expansion-cache.d.ts.map +1 -0
- package/dist/points-lines/inspection.d.ts +53 -0
- package/dist/points-lines/inspection.d.ts.map +1 -0
- package/dist/points-lines/prepare.d.ts +67 -0
- package/dist/points-lines/prepare.d.ts.map +1 -0
- package/dist/points-lines/record.d.ts +60 -0
- package/dist/points-lines/record.d.ts.map +1 -0
- package/dist/points-lines/snapshot.d.ts +49 -0
- package/dist/points-lines/snapshot.d.ts.map +1 -0
- package/dist/post-process-errors.d.ts +182 -0
- package/dist/post-process-errors.d.ts.map +1 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts +59 -0
- package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -0
- package/dist/record/__tests__/material-bg-cache.unit.test.d.ts +2 -0
- package/dist/record/__tests__/material-bg-cache.unit.test.d.ts.map +1 -0
- package/dist/record/__tests__/material-slot-plan.unit.test.d.ts +2 -0
- package/dist/record/__tests__/material-slot-plan.unit.test.d.ts.map +1 -0
- package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts +2 -0
- package/dist/record/__tests__/typed-frame-graph-plan.unit.test.d.ts.map +1 -0
- package/dist/record/__tests__/video-texture-view.unit.test.d.ts +2 -0
- package/dist/record/__tests__/video-texture-view.unit.test.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +121 -0
- package/dist/record/frame-lighting.d.ts.map +1 -0
- package/dist/record/frame-snapshot.d.ts +429 -0
- package/dist/record/frame-snapshot.d.ts.map +1 -0
- package/dist/record/frame-targets.d.ts +20 -0
- package/dist/record/frame-targets.d.ts.map +1 -0
- package/dist/record/frame.d.ts +71 -0
- package/dist/record/frame.d.ts.map +1 -0
- package/dist/record/helpers.d.ts +102 -0
- package/dist/record/helpers.d.ts.map +1 -0
- package/dist/record/main-pass-geometry.d.ts +28 -0
- package/dist/record/main-pass-geometry.d.ts.map +1 -0
- package/dist/record/main-pass-material.d.ts +204 -0
- package/dist/record/main-pass-material.d.ts.map +1 -0
- package/dist/record/main-pass-sprite-draws.d.ts +43 -0
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -0
- package/dist/record/main-pass.d.ts +20 -0
- package/dist/record/main-pass.d.ts.map +1 -0
- package/dist/record/mesh-ssbo.d.ts +446 -0
- package/dist/record/mesh-ssbo.d.ts.map +1 -0
- package/dist/record/render-context.d.ts +252 -0
- package/dist/record/render-context.d.ts.map +1 -0
- package/dist/record/shadow-pass.d.ts +52 -0
- package/dist/record/shadow-pass.d.ts.map +1 -0
- package/dist/record/skybox-post-pass.d.ts +33 -0
- package/dist/record/skybox-post-pass.d.ts.map +1 -0
- package/dist/record/typed-frame-graph.d.ts +35 -0
- package/dist/record/typed-frame-graph.d.ts.map +1 -0
- package/dist/record/view-ubo.d.ts +45 -0
- package/dist/record/view-ubo.d.ts.map +1 -0
- package/dist/render-contract.d.ts +424 -0
- package/dist/render-contract.d.ts.map +1 -0
- package/dist/render-data.d.ts +143 -0
- package/dist/render-data.d.ts.map +1 -0
- package/dist/render-graph-primitives.d.ts +76 -0
- package/dist/render-graph-primitives.d.ts.map +1 -0
- package/dist/render-pipeline.d.ts +110 -0
- package/dist/render-pipeline.d.ts.map +1 -0
- package/dist/render-system-extract.d.ts +868 -0
- package/dist/render-system-extract.d.ts.map +1 -0
- package/dist/render-system.d.ts +125 -0
- package/dist/render-system.d.ts.map +1 -0
- package/dist/scene/render-scene-types.d.ts +61 -0
- package/dist/scene/render-scene-types.d.ts.map +1 -0
- package/dist/scene/render-scene.d.ts +112 -0
- package/dist/scene/render-scene.d.ts.map +1 -0
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts +30 -0
- package/dist/scene-instances/post-spawn-resolve-joints.d.ts.map +1 -0
- package/dist/shadow-atlas.d.ts +117 -0
- package/dist/shadow-atlas.d.ts.map +1 -0
- package/dist/ssao-buffers.d.ts +50 -0
- package/dist/ssao-buffers.d.ts.map +1 -0
- package/dist/ssao-config.d.ts +28 -0
- package/dist/ssao-config.d.ts.map +1 -0
- package/dist/systems/active-camera.d.ts +53 -0
- package/dist/systems/active-camera.d.ts.map +1 -0
- package/dist/systems/pass-selector.d.ts +24 -0
- package/dist/systems/pass-selector.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts +49 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -0
- package/dist/systems/skin-palette-types.d.ts +14 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -0
- package/dist/systems/transparent-sort-config.d.ts +112 -0
- package/dist/systems/transparent-sort-config.d.ts.map +1 -0
- package/dist/tilemap-chunk-extract-system.d.ts +143 -0
- package/dist/tilemap-chunk-extract-system.d.ts.map +1 -0
- package/dist/typed-render-graph-primitives.d.ts +57 -0
- package/dist/typed-render-graph-primitives.d.ts.map +1 -0
- package/dist/typed-shadow-passes.d.ts +11 -0
- package/dist/typed-shadow-passes.d.ts.map +1 -0
- package/package.json +94 -0
- package/src/__tests__/authoring-path.unit.test.ts +23 -0
- package/src/__tests__/backend-selection-rhi-capture.test-d.ts +21 -0
- package/src/__tests__/callback-inference.test-d.ts +8 -0
- package/src/__tests__/cluster-binner.test.ts +272 -0
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +20 -0
- package/src/__tests__/construct-renderer-identity.unit.test.ts +23 -0
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +151 -0
- package/src/__tests__/device-scope-stale-matrix.unit.test.ts +42 -0
- package/src/__tests__/direct-extract-consumer-contract.test-d.ts +23 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +61 -0
- package/src/__tests__/factory-contract.integration.test.ts +280 -0
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +15 -0
- package/src/__tests__/frame-observation.contract.test.ts +112 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +32 -0
- package/src/__tests__/glyph-text-layout-recovery.unit.test.ts +167 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +350 -0
- package/src/__tests__/gpu-driven-indirect-raster.browser.test.ts +12 -0
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +16 -0
- package/src/__tests__/gpu-driven-production.integration.test.ts +436 -0
- package/src/__tests__/gpu-driven-scaling.unit.test.ts +87 -0
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +271 -0
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +290 -0
- package/src/__tests__/gpu-driven-view-reference.ts +111 -0
- package/src/__tests__/gpu-driven-view.browser.test.ts +30 -0
- package/src/__tests__/gpu-driven-view.dawn.test.ts +28 -0
- package/src/__tests__/gpu-driven-view.unit.test.ts +199 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +59 -0
- package/src/__tests__/gpu-scene-render-graph-gpu.ts +308 -0
- package/src/__tests__/gpu-scene-render-graph.browser.test.ts +19 -0
- package/src/__tests__/gpu-scene-render-graph.dawn.test.ts +19 -0
- package/src/__tests__/gpu-scene-schema.unit.test.ts +16 -0
- package/src/__tests__/gpu-scene.dawn.test.ts +205 -0
- package/src/__tests__/gpu-scene.unit.test.ts +147 -0
- package/src/__tests__/ibl/face-uniforms.unit.test.ts +46 -0
- package/src/__tests__/infinite-grid-no-vertex-probe.unit.test.ts +92 -0
- package/src/__tests__/injection-kind-owner.test-d.ts +14 -0
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +728 -0
- package/src/__tests__/light-buffer-layout.unit.test.ts +40 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +24 -0
- package/src/__tests__/material-cooked-projection.unit.test.ts +150 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +53 -0
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +94 -0
- package/src/__tests__/material-stride-surface.unit.test.ts +32 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +106 -0
- package/src/__tests__/mesh-material-bindings.unit.test.ts +89 -0
- package/src/__tests__/mesh-stride-surface.unit.test.ts +16 -0
- package/src/__tests__/morph-culling-reentry.dawn.test.ts +157 -0
- package/src/__tests__/morph-feature-gpu-work.integration.test.ts +80 -0
- package/src/__tests__/morph-feature-plan.unit.test.ts +53 -0
- package/src/__tests__/morph-visual-evidence.integration.test.ts +80 -0
- package/src/__tests__/nineslice-handle-surface.unit.test.ts +19 -0
- package/src/__tests__/post-process-error-policy-owner.unit.test.ts +201 -0
- package/src/__tests__/prepared-buffer-kind-owner.test-d.ts +29 -0
- package/src/__tests__/prepared-graphics-capability.unit.test.ts +65 -0
- package/src/__tests__/prepared-graphics-generation.unit.test.ts +161 -0
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +138 -0
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +29 -0
- package/src/__tests__/prepared-graphics-resolver.unit.test.ts +285 -0
- package/src/__tests__/prepared-graphics-snapshot.unit.test.ts +105 -0
- package/src/__tests__/prepared-graphics-store.unit.test.ts +154 -0
- package/src/__tests__/prepared-graphics-validation.unit.test.ts +176 -0
- package/src/__tests__/profiler-default-off.test.ts +22 -0
- package/src/__tests__/profiler-phase-catalog.test.ts +66 -0
- package/src/__tests__/profiler-phase-integration.test.ts +62 -0
- package/src/__tests__/profiler-phase-token.test.ts +79 -0
- package/src/__tests__/public-surface.test-d.ts +94 -0
- package/src/__tests__/recover-error-policy-owner.unit.test.ts +107 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +116 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +139 -0
- package/src/__tests__/render-error-exhaustive.test-d.ts +110 -0
- package/src/__tests__/render-feature-assembly.test-d.ts +43 -0
- package/src/__tests__/render-feature-context.test-d.ts +57 -0
- package/src/__tests__/render-feature-contract.test-d.ts +49 -0
- package/src/__tests__/render-feature-diagnostics.unit.test.ts +149 -0
- package/src/__tests__/render-feature-docs.unit.test.ts +89 -0
- package/src/__tests__/render-feature-errors.unit.test.ts +47 -0
- package/src/__tests__/render-feature-gpu-work.integration.test.ts +316 -0
- package/src/__tests__/render-feature-plan.test-d.ts +161 -0
- package/src/__tests__/render-feature-plan.unit.test.ts +170 -0
- package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +90 -0
- package/src/__tests__/render-feature-prepared-errors.test-d.ts +79 -0
- package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +80 -0
- package/src/__tests__/render-feature-prepared-graphics-isolation.unit.test.ts +72 -0
- package/src/__tests__/render-feature-prepared-graphics-negative.test-d.ts +36 -0
- package/src/__tests__/render-feature-prepared-graphics.test-d.ts +74 -0
- package/src/__tests__/render-feature-prepared-graphics.unit.test.ts +121 -0
- package/src/__tests__/render-feature-public-surface.test-d.ts +57 -0
- package/src/__tests__/render-feature-retry.unit.test.ts +87 -0
- package/src/__tests__/render-feature-scheduling.unit.test.ts +110 -0
- package/src/__tests__/render-feature-stage-failed-policy-owner.unit.test.ts +137 -0
- package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +146 -0
- package/src/__tests__/render-feature-visibility-context.test-d.ts +33 -0
- package/src/__tests__/render-feature-visibility-context.unit.test.ts +37 -0
- package/src/__tests__/render-feature-zero-work.unit.test.ts +76 -0
- package/src/__tests__/render-graph-compute-raster-gpu.ts +342 -0
- package/src/__tests__/render-graph-compute-raster.browser.test.ts +16 -0
- package/src/__tests__/render-graph-compute-raster.dawn.test.ts +22 -0
- package/src/__tests__/render-graph-hzb-gpu.ts +239 -0
- package/src/__tests__/render-graph-hzb.browser.test.ts +16 -0
- package/src/__tests__/render-graph-hzb.dawn.test.ts +23 -0
- package/src/__tests__/render-graph-primitives.unit.test.ts +22 -0
- package/src/__tests__/render-graph-storage-indirect-gpu.ts +162 -0
- package/src/__tests__/render-graph-storage-indirect.browser.test.ts +21 -0
- package/src/__tests__/render-graph-storage-indirect.dawn.test.ts +28 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +168 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +121 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +58 -0
- package/src/__tests__/rhi-backend-package-boundary.unit.test.ts +11 -0
- package/src/__tests__/scriptable-pack-consumer.test-d.ts +14 -0
- package/src/__tests__/shader-stage-surface.unit.test.ts +43 -0
- package/src/__tests__/ssao-config.unit.test.ts +36 -0
- package/src/__tests__/ssao-kernel-surface.unit.test.ts +14 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +28 -0
- package/src/__tests__/standard-descriptors.test-d.ts +22 -0
- package/src/__tests__/standard-pipeline.dawn.test.ts +61 -0
- package/src/__tests__/standard-pipeline.integration.test.ts +124 -0
- package/src/__tests__/standard-profile-oracle.unit.test.ts +62 -0
- package/src/__tests__/surface-configuration.unit.test.ts +91 -0
- package/src/__tests__/texture-usage-surface.unit.test.ts +58 -0
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +223 -0
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +42 -0
- package/src/__tests__/urp-pipeline.unit.test.ts +14 -0
- package/src/__tests__/vertex-color-pipeline.unit.test.ts +132 -0
- package/src/__tests__/vertex-layout-consumer.unit.test.ts +25 -0
- package/src/__tests__/visibility-diagnostics.integration.test.ts +62 -0
- package/src/__tests__/visibility-extract.integration.test.ts +98 -0
- package/src/__tests__/visibility-extract.perf.test.ts +130 -0
- package/src/__tests__/visibility-feature-dedup.integration.test.ts +55 -0
- package/src/__tests__/visibility-hidden-report.unit.test.ts +36 -0
- package/src/__tests__/visibility-instances.integration.test.ts +46 -0
- package/src/__tests__/visibility-multi-world.integration.test.ts +86 -0
- package/src/__tests__/visibility-producer-matrix.integration.test.ts +168 -0
- package/src/__tests__/visibility-producer-matrix.unit.test.ts +96 -0
- package/src/__tests__/visibility-public-surface.test-d.ts +27 -0
- package/src/__tests__/visibility-resolver.unit.test.ts +85 -0
- package/src/__tests__/visibility-resource-short-circuit.unit.test.ts +80 -0
- package/src/__tests__/visibility-snapshot-contract.unit.test.ts +60 -0
- package/src/__tests__/vocabulary.unit.test.ts +21 -0
- package/src/assembly/backend-contract.ts +57 -0
- package/src/assembly/factory.ts +8130 -0
- package/src/assembly/host-contract.ts +101 -0
- package/src/assembly/material/assembly.ts +48 -0
- package/src/assembly/material/pipeline-projection.ts +63 -0
- package/src/assets/asset-decoders.ts +158 -0
- package/src/assets/render-asset-port.ts +44 -0
- package/src/assets/resolve-render-asset.ts +13 -0
- package/src/authoring.ts +17 -0
- package/src/cluster-binner.ts +700 -0
- package/src/components/__tests__/points-lines-admission.unit.test.ts +219 -0
- package/src/components/__tests__/points-lines-schema.unit.test.ts +56 -0
- package/src/components/__tests__/schema-contract.unit.test.ts +10 -0
- package/src/components/__tests__/schema-parity.unit.test.ts +25 -0
- package/src/components/__tests__/visibility-schema.unit.test.ts +35 -0
- package/src/components/camera.ts +512 -0
- package/src/components/directional-light.ts +120 -0
- package/src/components/glyph-text.ts +64 -0
- package/src/components/index.ts +54 -0
- package/src/components/instances.ts +206 -0
- package/src/components/layer.ts +69 -0
- package/src/components/light-helpers.ts +188 -0
- package/src/components/lines.ts +18 -0
- package/src/components/mesh-filter.ts +60 -0
- package/src/components/mesh-renderer.ts +61 -0
- package/src/components/point-light-shadow.ts +43 -0
- package/src/components/point-light.ts +65 -0
- package/src/components/points.ts +40 -0
- package/src/components/post-process-params.ts +35 -0
- package/src/components/scene-instance.ts +193 -0
- package/src/components/skybox-background.ts +103 -0
- package/src/components/skylight.ts +97 -0
- package/src/components/sort-key.ts +75 -0
- package/src/components/spot-light.ts +124 -0
- package/src/components/sprite-animation.ts +168 -0
- package/src/components/sprite-instances.ts +179 -0
- package/src/components/sprite-playback-mode.ts +79 -0
- package/src/components/sprite-region-override.ts +105 -0
- package/src/components/tile-layer.ts +167 -0
- package/src/components/tilemap.ts +48 -0
- package/src/components/visibility.ts +53 -0
- package/src/construct-renderer.ts +67 -0
- package/src/debug-draw-glue.ts +48 -0
- package/src/device/device-scope.ts +306 -0
- package/src/device/gpu-residency.ts +1822 -0
- package/src/device/resource-types.ts +20 -0
- package/src/engine-metrics.ts +82 -0
- package/src/errors/ecs-validation.ts +16 -0
- package/src/errors/index.ts +3 -0
- package/src/errors/recover.ts +161 -0
- package/src/errors/render.ts +1284 -0
- package/src/extract/visibility.ts +120 -0
- package/src/features/fullscreen.ts +46 -0
- package/src/features/host.ts +1363 -0
- package/src/features/morph/morph-feature.ts +377 -0
- package/src/features/plan.ts +447 -0
- package/src/features/prepared-gpu-work.ts +959 -0
- package/src/features/prepared-graphics-store.ts +449 -0
- package/src/features/prepared-graphics.ts +420 -0
- package/src/features/render-graph-compute.ts +69 -0
- package/src/features/render-graph-contribution.ts +75 -0
- package/src/features/render-graph-raster.ts +332 -0
- package/src/features/render-graph-resources.ts +38 -0
- package/src/features/targets.ts +70 -0
- package/src/features/types.ts +103 -0
- package/src/features/vocabulary.ts +24 -0
- package/src/fullscreen-post-process-pass.ts +363 -0
- package/src/glyph-text-layout-system.ts +421 -0
- package/src/gpu-driven/batch-topology.ts +245 -0
- package/src/gpu-driven/production-raster.ts +695 -0
- package/src/gpu-driven/view-gpu.ts +703 -0
- package/src/gpu-resource.ts +159 -0
- package/src/gpu-scene-schema.ts +136 -0
- package/src/gpu-scene.ts +722 -0
- package/src/gpu-stage.ts +9 -0
- package/src/gpu-texture-usage.ts +12 -0
- package/src/gpu-usage.ts +14 -0
- package/src/hdrp-buffers.ts +480 -0
- package/src/ibl/IblPipelineCache.ts +1006 -0
- package/src/ibl/skylight-bind-group.ts +513 -0
- package/src/index.ts +129 -0
- package/src/inspection-types.ts +80 -0
- package/src/instance-buffer-cache.ts +95 -0
- package/src/internal.ts +9 -0
- package/src/lifecycle.ts +168 -0
- package/src/light-buffer-layout.ts +346 -0
- package/src/materials.ts +214 -0
- package/src/mesh-material-bindings.ts +103 -0
- package/src/pbr-pipeline.ts +1137 -0
- package/src/pipeline/standard-forward-lane.ts +229 -0
- package/src/pipeline/standard-pipeline.ts +555 -0
- package/src/pipeline/standard-profile.ts +65 -0
- package/src/pipeline-builder.ts +382 -0
- package/src/pipeline-spec-types.ts +28 -0
- package/src/pipeline-spec.ts +1231 -0
- package/src/plugin.ts +69 -0
- package/src/points-lines/__tests__/bounds.unit.test.ts +21 -0
- package/src/points-lines/__tests__/cache-recovery.unit.test.ts +157 -0
- package/src/points-lines/__tests__/inspection-lanes.integration.test.ts +146 -0
- package/src/points-lines/__tests__/inspection.unit.test.ts +173 -0
- package/src/points-lines/__tests__/lane-structural.integration.test.ts +122 -0
- package/src/points-lines/__tests__/points-lines.bench.ts +400 -0
- package/src/points-lines/__tests__/raster-lane.integration.test.ts +44 -0
- package/src/points-lines/__tests__/snapshot.unit.test.ts +101 -0
- package/src/points-lines/__tests__/view-ubo.unit.test.ts +73 -0
- package/src/points-lines/admission.ts +238 -0
- package/src/points-lines/bounds.ts +23 -0
- package/src/points-lines/expansion-cache.ts +215 -0
- package/src/points-lines/inspection.ts +97 -0
- package/src/points-lines/prepare.ts +177 -0
- package/src/points-lines/record.ts +125 -0
- package/src/points-lines/snapshot.ts +130 -0
- package/src/post-process-errors.ts +302 -0
- package/src/prepare/prepared-graphics-resolver.ts +456 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +41 -0
- package/src/record/__tests__/material-slot-plan.unit.test.ts +44 -0
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +41 -0
- package/src/record/__tests__/video-texture-view.unit.test.ts +90 -0
- package/src/record/frame-lighting.ts +1074 -0
- package/src/record/frame-snapshot.ts +500 -0
- package/src/record/frame-targets.ts +137 -0
- package/src/record/frame.ts +1598 -0
- package/src/record/helpers.ts +284 -0
- package/src/record/main-pass-geometry.ts +1065 -0
- package/src/record/main-pass-material.ts +1043 -0
- package/src/record/main-pass-sprite-draws.ts +1137 -0
- package/src/record/main-pass.ts +610 -0
- package/src/record/mesh-ssbo.ts +885 -0
- package/src/record/render-context.ts +384 -0
- package/src/record/shadow-pass.ts +698 -0
- package/src/record/skybox-post-pass.ts +593 -0
- package/src/record/typed-frame-graph.ts +461 -0
- package/src/record/view-ubo.ts +222 -0
- package/src/render-contract.ts +582 -0
- package/src/render-data.ts +385 -0
- package/src/render-graph-primitives.ts +811 -0
- package/src/render-pipeline.ts +259 -0
- package/src/render-system-extract.ts +4585 -0
- package/src/render-system.ts +1933 -0
- package/src/scene/render-scene-types.ts +67 -0
- package/src/scene/render-scene.ts +1087 -0
- package/src/scene-instances/post-spawn-resolve-joints.ts +165 -0
- package/src/shadow-atlas.ts +244 -0
- package/src/ssao-buffers.ts +334 -0
- package/src/ssao-config.ts +61 -0
- package/src/systems/active-camera.ts +116 -0
- package/src/systems/pass-selector.ts +49 -0
- package/src/systems/skin-palette-allocator.ts +251 -0
- package/src/systems/skin-palette-types.ts +14 -0
- package/src/systems/transparent-sort-config.ts +233 -0
- package/src/tilemap-chunk-extract-system.ts +1290 -0
- package/src/typed-render-graph-primitives.ts +541 -0
- package/src/typed-shadow-passes.ts +165 -0
|
@@ -0,0 +1,1137 @@
|
|
|
1
|
+
// @forgeax/engine-runtime - RenderSystem record stage: main-pass sprite draws.
|
|
2
|
+
// feat-20260704 M5/w31: further-split from main-pass.ts (AC-05 <=1500 lines/file).
|
|
3
|
+
// recordSpritePass + sprite entity/transparent/instance-buffer helpers, moved verbatim.
|
|
4
|
+
|
|
5
|
+
import type { World } from '@forgeax/engine-ecs';
|
|
6
|
+
import {
|
|
7
|
+
type BindGroup,
|
|
8
|
+
type Buffer,
|
|
9
|
+
type RenderPipeline,
|
|
10
|
+
RhiError,
|
|
11
|
+
type RhiRenderPassEncoder,
|
|
12
|
+
} from '@forgeax/engine-rhi';
|
|
13
|
+
import type { Handle, MaterialRenderState } from '@forgeax/engine-types';
|
|
14
|
+
import { GpuBuffer } from '../gpu-resource';
|
|
15
|
+
import {
|
|
16
|
+
GPU_BUFFER_USAGE_COPY_DST,
|
|
17
|
+
GPU_BUFFER_USAGE_STORAGE,
|
|
18
|
+
GPU_BUFFER_USAGE_UNIFORM,
|
|
19
|
+
} from '../gpu-usage';
|
|
20
|
+
import {
|
|
21
|
+
assembleMaterialWithSkylightEntries,
|
|
22
|
+
type EmissiveAoBindGroupResources,
|
|
23
|
+
type SkylightBindGroupResources,
|
|
24
|
+
} from '../ibl/skylight-bind-group';
|
|
25
|
+
import type { InstanceBufferCacheEntry } from '../instance-buffer-cache';
|
|
26
|
+
import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from '../materials';
|
|
27
|
+
import { SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET } from '../pbr-pipeline';
|
|
28
|
+
import {
|
|
29
|
+
buildBeginRenderPassDescriptor,
|
|
30
|
+
variantSetFromVertexLayoutProjection,
|
|
31
|
+
} from '../pipeline-spec';
|
|
32
|
+
import type { MaterialSnapshot, SpriteInstancesSnapshot } from '../render-system-extract';
|
|
33
|
+
import { worldEntityKey } from './frame-snapshot';
|
|
34
|
+
import { entityHasTransparentSubmesh, residentTextureView } from './main-pass-material';
|
|
35
|
+
import {
|
|
36
|
+
extractEntryResourceHandle,
|
|
37
|
+
getOrCreatePerEntity,
|
|
38
|
+
MAX_UNIFORM_INSTANCES,
|
|
39
|
+
MESH_PER_ENTITY_STRIDE,
|
|
40
|
+
packInstanceStorageBuffer,
|
|
41
|
+
} from './mesh-ssbo';
|
|
42
|
+
import type { _InternalRenderPipelineContext } from './render-context';
|
|
43
|
+
import { MATERIAL_PER_ENTITY_STRIDE, STANDARD_PBR_UBO_SIZE } from './render-context';
|
|
44
|
+
|
|
45
|
+
export type { SpriteInstancesSnapshot };
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Build the interleaved sprite instance payload consumed by this record owner.
|
|
49
|
+
* The extract stage validates the two packed arrays before they reach this
|
|
50
|
+
* function, so the record path has one source of count-mismatch errors.
|
|
51
|
+
*/
|
|
52
|
+
export function interleaveSpriteInstanceBuffer(
|
|
53
|
+
transforms: Float32Array,
|
|
54
|
+
regions: Float32Array,
|
|
55
|
+
includePrevious = false,
|
|
56
|
+
): Float32Array {
|
|
57
|
+
const count = transforms.length / 16;
|
|
58
|
+
const stride = includePrevious ? 36 : 20;
|
|
59
|
+
const regionOffset = includePrevious ? 32 : 16;
|
|
60
|
+
const out = new Float32Array(count * stride);
|
|
61
|
+
for (let i = 0; i < count; i++) {
|
|
62
|
+
const dstBase = i * stride;
|
|
63
|
+
const transformBase = i * 16;
|
|
64
|
+
const regionBase = i * 4;
|
|
65
|
+
for (let k = 0; k < 16; k++) out[dstBase + k] = transforms[transformBase + k] ?? 0;
|
|
66
|
+
if (includePrevious) {
|
|
67
|
+
for (let k = 0; k < 16; k++) {
|
|
68
|
+
out[dstBase + 16 + k] = transforms[transformBase + k] ?? 0;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (let k = 0; k < 4; k++) {
|
|
72
|
+
out[dstBase + regionOffset + k] = regions[regionBase + k] ?? 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check whether the existing per-entity sprite buffer still matches the
|
|
80
|
+
* extract snapshot and interleaved byte count.
|
|
81
|
+
*/
|
|
82
|
+
export function spriteInstancesCacheHit(
|
|
83
|
+
entry: InstanceBufferCacheEntry | undefined,
|
|
84
|
+
snapshot: SpriteInstancesSnapshot,
|
|
85
|
+
requestedBytes: number,
|
|
86
|
+
): boolean {
|
|
87
|
+
return (
|
|
88
|
+
entry !== undefined &&
|
|
89
|
+
entry.uploadedArchVersion === snapshot.archVersion &&
|
|
90
|
+
entry.uploadedByteLength === requestedBytes
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Decide whether the LDR record needs the transparent sprite sub-pass. This
|
|
96
|
+
* remains beside the sprite record owner so the frame stage and draw stage
|
|
97
|
+
* share the same transparent-material rule.
|
|
98
|
+
*/
|
|
99
|
+
export function computeSplitLdrSprite(
|
|
100
|
+
validatedOrdered: readonly (
|
|
101
|
+
| {
|
|
102
|
+
readonly source: {
|
|
103
|
+
readonly material: MaterialSnapshot;
|
|
104
|
+
readonly materials?: readonly MaterialSnapshot[];
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
| undefined
|
|
108
|
+
)[],
|
|
109
|
+
tonemapActive: boolean,
|
|
110
|
+
): boolean {
|
|
111
|
+
if (tonemapActive) return false;
|
|
112
|
+
for (const entry of validatedOrdered) {
|
|
113
|
+
if (entry === undefined) continue;
|
|
114
|
+
const materials = entry.source.materials;
|
|
115
|
+
if (materials !== undefined) {
|
|
116
|
+
if (materials.some((material) => material.transparent === true)) return true;
|
|
117
|
+
} else if (entry.source.material.transparent === true) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* feat-20260704 M3/w19: LDR sprite split sub-pass, extracted verbatim from
|
|
126
|
+
* recordMainPass. Runs after the geometry pass when there are sprite / LDR
|
|
127
|
+
* transparent entities and the split path is active (splitLdrSprite && a raw
|
|
128
|
+
* unorm swap-chain view exists). Ends the geometry `pass`, opens a `spritePass`
|
|
129
|
+
* on the resolved transparent-pass view (loadOp=load), draws the sprite / sprite-lit
|
|
130
|
+
* entities (fold-instanced where possible) then the generic per-submesh
|
|
131
|
+
* transparent PBR submeshes, and ends the sprite pass. Returns the updated
|
|
132
|
+
* `geometryPassEnded` flag so the caller skips the unconditional pass.end().
|
|
133
|
+
*
|
|
134
|
+
* @internal
|
|
135
|
+
*/
|
|
136
|
+
export function recordSpritePass(
|
|
137
|
+
c: _InternalRenderPipelineContext,
|
|
138
|
+
pass: RhiRenderPassEncoder,
|
|
139
|
+
matchedIndices: Set<number> | null,
|
|
140
|
+
materialSlotIndices: readonly (readonly number[])[],
|
|
141
|
+
sampleCount: number,
|
|
142
|
+
resolveMaterialBindGroup: (
|
|
143
|
+
materialSlot: number,
|
|
144
|
+
submeshMaterial: MaterialSnapshot,
|
|
145
|
+
entityKey: number,
|
|
146
|
+
materialWorld: World,
|
|
147
|
+
) => BindGroup,
|
|
148
|
+
skylightResources: SkylightBindGroupResources,
|
|
149
|
+
graphPass?: RhiRenderPassEncoder,
|
|
150
|
+
): boolean {
|
|
151
|
+
const {
|
|
152
|
+
runtime,
|
|
153
|
+
pipelineState,
|
|
154
|
+
encoder,
|
|
155
|
+
msaaActive,
|
|
156
|
+
ldrSpritePassView,
|
|
157
|
+
ldrSpriteColorView,
|
|
158
|
+
geometryDepthView,
|
|
159
|
+
viewBindGroup,
|
|
160
|
+
splitLdrSprite,
|
|
161
|
+
} = c;
|
|
162
|
+
let geometryPassEnded = false;
|
|
163
|
+
if (splitLdrSprite && (graphPass !== undefined || ldrSpritePassView !== null)) {
|
|
164
|
+
if (graphPass === undefined) {
|
|
165
|
+
pass.end();
|
|
166
|
+
geometryPassEnded = true;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// feat-20260604 M2 / w9 (F-1): under MSAA the sprite sub-pass writes the
|
|
170
|
+
// count=4 transparent-pass view of the SAME multisample texture the
|
|
171
|
+
// geometry pass wrote (loadOp=load preserves geometry under sprites) and
|
|
172
|
+
// resolves the combined result to the single-sample transparent-pass
|
|
173
|
+
// view at this (last) pass end. Depth reuses the shared count=4
|
|
174
|
+
// multisample depth (depthLoadOp=load preserves sprite-vs-mesh occlusion).
|
|
175
|
+
// The single-
|
|
176
|
+
// sample path is byte-for-byte unchanged (writes the swap-chain view).
|
|
177
|
+
const spriteColorView = msaaActive ? ldrSpriteColorView : ldrSpritePassView;
|
|
178
|
+
// sprite-split sub-pass: forward shape with both color and depth loaded
|
|
179
|
+
// (preserves prior content from the main forward pass under the sprites).
|
|
180
|
+
// Stencil ops auto-emitted by the helper because depthFormat carries
|
|
181
|
+
// stencil8.
|
|
182
|
+
const spritePass: RhiRenderPassEncoder =
|
|
183
|
+
graphPass ??
|
|
184
|
+
encoder.beginRenderPass(
|
|
185
|
+
buildBeginRenderPassDescriptor(
|
|
186
|
+
{
|
|
187
|
+
// SSOT for the sprite-pass color format is the resolved transparent
|
|
188
|
+
// attachment. Native linear-LDR frames use graph-owned `ldrColor`
|
|
189
|
+
// (possibly rgba16float); swap-chain fallback frames use their raw
|
|
190
|
+
// storage format. WebGPU requires the attachment format and PSO
|
|
191
|
+
// target to match, so both are resolved by the same helper.
|
|
192
|
+
colorFormats: [transparentPassColorFormat(c) as GPUTextureFormat],
|
|
193
|
+
depthFormat: 'depth24plus-stencil8',
|
|
194
|
+
sampleCount: msaaActive ? 4 : 1,
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
colorViews: [spriteColorView],
|
|
198
|
+
depthView: geometryDepthView,
|
|
199
|
+
...(msaaActive ? { resolveTargets: [ldrSpritePassView] } : {}),
|
|
200
|
+
},
|
|
201
|
+
'forward',
|
|
202
|
+
{ colorLoadOp: 'load', depthLoadOp: 'load' },
|
|
203
|
+
) as never,
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
spritePass.setBindGroup(0, viewBindGroup as BindGroup, [0]);
|
|
207
|
+
|
|
208
|
+
// feat-20260625-refactor-sprite-as-transparent-mesh M3 / w14 (D-7):
|
|
209
|
+
// sprite PSO resolution migrated from the dedicated boot-time PSO
|
|
210
|
+
// fields (deleted) to the generic per-MaterialShader pipeline cache.
|
|
211
|
+
// feat-20260626-collapse M2 / M2-T2: blend factor pair literal moved
|
|
212
|
+
// to the public `SPRITE_PREMULTIPLIED_ALPHA_BLEND` named constant
|
|
213
|
+
// (re-exported from `@forgeax/engine-runtime`) so each AI user
|
|
214
|
+
// building a transparent material declares the same blend by
|
|
215
|
+
// reference; the previous implicit blend-state factory helper is
|
|
216
|
+
// gone. Cache miss still surfaces as a structured
|
|
217
|
+
// `shader-compile-failed` RhiError mirroring the pre-w14 behaviour.
|
|
218
|
+
//
|
|
219
|
+
// feat-20260608-tilemap-object-layer-rendering M2 / m2-t6 (D-8): sprite
|
|
220
|
+
// pipeline cullMode='none'. H/V flip via negative scale x/y (tilemap
|
|
221
|
+
// per-cell entity TRS form) inverts the triangle winding; cullMode='back'
|
|
222
|
+
// would throw the flipped quad away. The sprite pass runs in the
|
|
223
|
+
// alpha-blend transparent bucket back-to-front already, so cullMode='none'
|
|
224
|
+
// adds no overdraw cost. Pre-feat-20260625 the dedicated spritePipeline
|
|
225
|
+
// hard-coded 'none' (deleted in w14); the generic path must replicate
|
|
226
|
+
// it here or the cullmode-flip dawn smoke goes black on negative-scale.
|
|
227
|
+
const spritePremulBlend: MaterialRenderState = {
|
|
228
|
+
depthWriteEnabled: false,
|
|
229
|
+
depthCompare: 'less-equal',
|
|
230
|
+
cullMode: 'none',
|
|
231
|
+
blend: SPRITE_PREMULTIPLIED_ALPHA_BLEND,
|
|
232
|
+
};
|
|
233
|
+
// bug-20260629: PR #526 added PER_INSTANCE_REGION as a second variant
|
|
234
|
+
// axis on sprite.wgsl. Build BOTH variants here; the per-entity loop
|
|
235
|
+
// picks the right one based on whether the entity carries a
|
|
236
|
+
// SpriteInstances snapshot:
|
|
237
|
+
// - spritePH (PER_INSTANCE_REGION=false): regular per-entity sprites
|
|
238
|
+
// + fold-bucket instanced draws (64-byte mat4 only instance buf);
|
|
239
|
+
// UV region comes from the material UBO `region` slot.
|
|
240
|
+
// - spritePH_withRegion (PER_INSTANCE_REGION=true): SpriteInstances
|
|
241
|
+
// entities with 80-byte interleaved (mat4 64B + region 16B) per
|
|
242
|
+
// instance; UV region comes from `instances[idx].region`.
|
|
243
|
+
//
|
|
244
|
+
// Without spritePH_withRegion the SpriteInstances data was uploaded
|
|
245
|
+
// but the shader read bytes 64-79 as region=0 → black quads.
|
|
246
|
+
//
|
|
247
|
+
// feat-20260624-sprite-lit-shading-model-pure-2d-lighting M1' / t7:
|
|
248
|
+
// sprite-lit walks the same LDR transparent split pass with mirror
|
|
249
|
+
// PSO request shape (only materialShaderId string differs). The
|
|
250
|
+
// sprite-lit PSO is fetched lazily per-entity below since the pass
|
|
251
|
+
// mixes sprite + sprite-lit transparent entities. PSO cache strings
|
|
252
|
+
// are isolated by `materialShaderId` (D-11), no slot collision.
|
|
253
|
+
const spritePH =
|
|
254
|
+
runtime.getMaterialShaderPipeline?.(
|
|
255
|
+
'forgeax::sprite',
|
|
256
|
+
/* isHdr */ false,
|
|
257
|
+
spritePremulBlend,
|
|
258
|
+
'triangle-list',
|
|
259
|
+
undefined,
|
|
260
|
+
undefined,
|
|
261
|
+
'forward',
|
|
262
|
+
undefined,
|
|
263
|
+
msaaActive ? 4 : 1,
|
|
264
|
+
// feat-20260625-refactor-sprite-as-transparent-mesh R2 fix-up:
|
|
265
|
+
// the split sub-pass PSO must use the same attachment format as the
|
|
266
|
+
// encoder. Native linear-LDR frames resolve graph-owned `ldrColor`
|
|
267
|
+
// (possibly rgba16float); swap-chain fallback frames resolve their raw
|
|
268
|
+
// storage format. `transparentPassColorFormat` is the single owner for
|
|
269
|
+
// this format so lazy PSO construction cannot fall back to the geometry
|
|
270
|
+
// sRGB view.
|
|
271
|
+
transparentPassColorFormat(c, pipelineState) as GPUTextureFormat,
|
|
272
|
+
) ?? null;
|
|
273
|
+
const spritePH_withRegion =
|
|
274
|
+
runtime.getMaterialShaderPipeline?.(
|
|
275
|
+
'forgeax::sprite',
|
|
276
|
+
/* isHdr */ false,
|
|
277
|
+
spritePremulBlend,
|
|
278
|
+
'triangle-list',
|
|
279
|
+
undefined,
|
|
280
|
+
SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET,
|
|
281
|
+
'forward',
|
|
282
|
+
undefined,
|
|
283
|
+
msaaActive ? 4 : 1,
|
|
284
|
+
transparentPassColorFormat(c) as GPUTextureFormat,
|
|
285
|
+
) ?? null;
|
|
286
|
+
|
|
287
|
+
// bug-20260629: spritePH===null check moved OUTSIDE the entity loop so the
|
|
288
|
+
// sprite pass is properly ended before returning. Inside the loop the early
|
|
289
|
+
// `return` left spritePass open → render-pass-not-ended error every frame
|
|
290
|
+
// where the pipeline is still being compiled (frame 0 on first load).
|
|
291
|
+
//
|
|
292
|
+
// feat-city-glb Bug 5: a missing sprite PSO must NOT abort the whole
|
|
293
|
+
// sub-pass — the generic per-submesh PBR transparent loop below does not
|
|
294
|
+
// depend on the sprite shader. Only skip the sprite ENTITIES when spritePH
|
|
295
|
+
// is null (fire the diagnostic once, iff a sprite entity is actually
|
|
296
|
+
// present), then fall through to the PBR loop. A PBR-only transparent
|
|
297
|
+
// scene (e.g. a glTF BLEND decal, no sprites) renders regardless of
|
|
298
|
+
// whether sprite.wgsl is in the manifest.
|
|
299
|
+
const spriteUnavailable = spritePH === null;
|
|
300
|
+
let spriteUnavailableReported = false;
|
|
301
|
+
const reportSpriteUnavailable = (): void => {
|
|
302
|
+
if (spriteUnavailableReported) return;
|
|
303
|
+
spriteUnavailableReported = true;
|
|
304
|
+
runtime.errorRegistry.fire(
|
|
305
|
+
new RhiError({
|
|
306
|
+
code: 'shader-compile-failed',
|
|
307
|
+
expected:
|
|
308
|
+
'manifest entries include sprite.wgsl + the engine triple (pbr + unlit + tonemap)',
|
|
309
|
+
hint: 'verify @forgeax/engine-vite-plugin-shader emits manifest.json with the 4 engine entries (sprite.wgsl is required when spawning sprite materials); check vite plugin engineEntries option',
|
|
310
|
+
}),
|
|
311
|
+
);
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// feat-20260624 M1' / t7: parallel sprite-lit PSO request — same
|
|
315
|
+
// arg shape, only materialShaderId differs.
|
|
316
|
+
const spriteLitPH =
|
|
317
|
+
runtime.getMaterialShaderPipeline?.(
|
|
318
|
+
'forgeax::sprite-lit',
|
|
319
|
+
/* isHdr */ false,
|
|
320
|
+
spritePremulBlend,
|
|
321
|
+
'triangle-list',
|
|
322
|
+
undefined,
|
|
323
|
+
undefined,
|
|
324
|
+
'forward',
|
|
325
|
+
undefined,
|
|
326
|
+
msaaActive ? 4 : 1,
|
|
327
|
+
transparentPassColorFormat(c) as GPUTextureFormat,
|
|
328
|
+
) ?? null;
|
|
329
|
+
|
|
330
|
+
recordSpriteEntityDraws(
|
|
331
|
+
c,
|
|
332
|
+
spritePass,
|
|
333
|
+
matchedIndices,
|
|
334
|
+
skylightResources,
|
|
335
|
+
spritePH,
|
|
336
|
+
spritePH_withRegion,
|
|
337
|
+
spriteLitPH,
|
|
338
|
+
spriteUnavailable,
|
|
339
|
+
reportSpriteUnavailable,
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
// feat-city-glb Bug 5 (per-submesh transparency): generic per-submesh PBR
|
|
343
|
+
// draws in the LDR blend sub-pass. The sprite loop above handles only true
|
|
344
|
+
// sprite / sprite-lit entities (whole-mesh sprite PSO). EVERY non-sprite
|
|
345
|
+
// transparent material — built-in PBR, single- or multi-submesh, incl.
|
|
346
|
+
// glTF alphaMode=BLEND (the crosswalk decal submesh AND the 4.3-blending
|
|
347
|
+
// window quad) — is drawn here with its real shader + per-submesh
|
|
348
|
+
// geometry, reusing the geometry pass's PBR machinery but rendering into
|
|
349
|
+
// the resolved transparent attachment (colorFormatOverride =
|
|
350
|
+
// transparentPassColorFormat(c)).
|
|
351
|
+
// Opaque submeshes of a mixed mesh were already drawn in the geometry pass
|
|
352
|
+
// (per-submesh skip there).
|
|
353
|
+
//
|
|
354
|
+
// Non-skinned, non-instanced (glTF static meshes): group 2 = the shared
|
|
355
|
+
// frame meshBindGroup with the per-entity dynamic offset; group 3 = the
|
|
356
|
+
// identity instance BG (drawIndexed instanceCount=1). Skinned / instanced
|
|
357
|
+
// transparent submeshes are OOS here (no such content) and fall through.
|
|
358
|
+
recordSpriteTransparentPbrDraws(
|
|
359
|
+
c,
|
|
360
|
+
spritePass,
|
|
361
|
+
matchedIndices,
|
|
362
|
+
materialSlotIndices,
|
|
363
|
+
sampleCount,
|
|
364
|
+
resolveMaterialBindGroup,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
if (graphPass === undefined) spritePass.end();
|
|
368
|
+
}
|
|
369
|
+
return geometryPassEnded;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* feat-20260704 M3/w19: generic per-submesh transparent PBR draws in the LDR
|
|
374
|
+
* blend sub-pass, extracted verbatim from the sprite split pass. Every
|
|
375
|
+
* non-sprite transparent material (built-in PBR, single- or multi-submesh, incl.
|
|
376
|
+
* glTF alphaMode=BLEND) draws here with its real shader + per-submesh geometry,
|
|
377
|
+
* reusing the geometry pass's PBR machinery but rendering into the resolved
|
|
378
|
+
* transparent attachment (colorFormatOverride = transparentPassColorFormat(c)). Opaque submeshes of a
|
|
379
|
+
* mixed mesh were already drawn in the geometry pass (per-submesh skip there).
|
|
380
|
+
* Sprites are handled by the sprite loop; skinned / instanced transparent
|
|
381
|
+
* submeshes are OOS here and fall through.
|
|
382
|
+
*
|
|
383
|
+
* @internal
|
|
384
|
+
*/
|
|
385
|
+
function recordSpriteTransparentPbrDraws(
|
|
386
|
+
c: _InternalRenderPipelineContext,
|
|
387
|
+
spritePass: RhiRenderPassEncoder,
|
|
388
|
+
matchedIndices: Set<number> | null,
|
|
389
|
+
materialSlotIndices: readonly (readonly number[])[],
|
|
390
|
+
sampleCount: number,
|
|
391
|
+
resolveMaterialBindGroup: (
|
|
392
|
+
materialSlot: number,
|
|
393
|
+
submeshMaterial: MaterialSnapshot,
|
|
394
|
+
entityKey: number,
|
|
395
|
+
materialWorld: World,
|
|
396
|
+
) => BindGroup,
|
|
397
|
+
): void {
|
|
398
|
+
const { runtime, pipelineState, frameState, bindGroupCounts, validatedOrdered, meshBindGroup } =
|
|
399
|
+
c;
|
|
400
|
+
let lastPbrSubPipelineHandle: typeof pipelineState.unlitPipeline = null;
|
|
401
|
+
let lastPbrSubVertexBuffer: GpuBuffer | null = null;
|
|
402
|
+
let lastPbrSubIndexBuffer: GpuBuffer | null = null;
|
|
403
|
+
for (let i = 0; i < validatedOrdered.length; i++) {
|
|
404
|
+
const entry = validatedOrdered[i];
|
|
405
|
+
if (entry === undefined) continue;
|
|
406
|
+
if (matchedIndices !== null && !matchedIndices.has(entry.renderableIndex)) continue;
|
|
407
|
+
// Sprites are handled by the sprite loop above; skip them here.
|
|
408
|
+
const entShaderId = entry.source.material.materialShaderId;
|
|
409
|
+
const entIsSprite = entShaderId === 'forgeax::sprite' || entShaderId === 'forgeax::sprite-lit';
|
|
410
|
+
if (entIsSprite) continue;
|
|
411
|
+
// Only entities that carry at least one transparent submesh reach a draw
|
|
412
|
+
// (single-submesh transparent PBR and mixed opaque+transparent meshes).
|
|
413
|
+
if (!entityHasTransparentSubmesh(entry.source)) continue;
|
|
414
|
+
// Skinned / instanced transparent submeshes are not supported in this
|
|
415
|
+
// sub-pass path (no such content today); skip to avoid mis-binding.
|
|
416
|
+
if (entry.source.skin !== undefined || entry.source.instances !== undefined) continue;
|
|
417
|
+
|
|
418
|
+
const matsForRebind = entry.source.materials;
|
|
419
|
+
if (entry.mesh.vertexBuffer !== lastPbrSubVertexBuffer) {
|
|
420
|
+
spritePass.setVertexBuffer(0, entry.mesh.vertexBuffer.handle);
|
|
421
|
+
lastPbrSubVertexBuffer = entry.mesh.vertexBuffer;
|
|
422
|
+
}
|
|
423
|
+
if (
|
|
424
|
+
entry.mesh.indexed &&
|
|
425
|
+
entry.mesh.indexBuffer !== null &&
|
|
426
|
+
entry.mesh.indexBuffer !== lastPbrSubIndexBuffer
|
|
427
|
+
) {
|
|
428
|
+
spritePass.setIndexBuffer(entry.mesh.indexBuffer.handle, entry.mesh.indexFormat);
|
|
429
|
+
lastPbrSubIndexBuffer = entry.mesh.indexBuffer;
|
|
430
|
+
}
|
|
431
|
+
spritePass.setBindGroup(2, meshBindGroup as BindGroup, [i * MESH_PER_ENTITY_STRIDE]);
|
|
432
|
+
// Identity instance BG (instanceCount=1); reuse the per-entity cache.
|
|
433
|
+
const identityInstBg: BindGroup = getOrCreatePerEntity(
|
|
434
|
+
frameState.instancesBgPerEntity,
|
|
435
|
+
worldEntityKey(entry.source.worldId, entry.source.entityKey),
|
|
436
|
+
[pipelineState.identityInstanceBuffer],
|
|
437
|
+
'instances',
|
|
438
|
+
() => {
|
|
439
|
+
const result = runtime.device.createBindGroup({
|
|
440
|
+
label: 'pbr-transparent-sub-instances-bg',
|
|
441
|
+
layout: pipelineState.instancesBindGroupLayout,
|
|
442
|
+
entries: [
|
|
443
|
+
{
|
|
444
|
+
binding: 0,
|
|
445
|
+
resource: {
|
|
446
|
+
kind: 'buffer',
|
|
447
|
+
value: { buffer: pipelineState.identityInstanceBuffer },
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
],
|
|
451
|
+
});
|
|
452
|
+
if (!result.ok) throw result.error;
|
|
453
|
+
return result.value;
|
|
454
|
+
},
|
|
455
|
+
bindGroupCounts,
|
|
456
|
+
);
|
|
457
|
+
spritePass.setBindGroup(3, identityInstBg);
|
|
458
|
+
|
|
459
|
+
const subVariantSet = frameState.isHdrpActive
|
|
460
|
+
? ''
|
|
461
|
+
: 'CLUSTER_FORWARD_AVAILABLE=false+STORAGE_BUFFER_AVAILABLE=true';
|
|
462
|
+
const projectionVariantSetResult = variantSetFromVertexLayoutProjection(
|
|
463
|
+
entry.mesh.layoutProjection,
|
|
464
|
+
subVariantSet,
|
|
465
|
+
);
|
|
466
|
+
if (!projectionVariantSetResult.ok) {
|
|
467
|
+
runtime.errorRegistry.fire(projectionVariantSetResult.error);
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
const projectionVariantSet = projectionVariantSetResult.value;
|
|
471
|
+
|
|
472
|
+
for (let smIdx = 0; smIdx < entry.mesh.submeshes.length; smIdx++) {
|
|
473
|
+
const sm = entry.mesh.submeshes[smIdx];
|
|
474
|
+
if (sm === undefined) continue;
|
|
475
|
+
const matSlotIdx = sm.materialSlot;
|
|
476
|
+
const submeshMaterial = matsForRebind[matSlotIdx] ?? entry.source.material;
|
|
477
|
+
// Only transparent submeshes belong in this blend sub-pass; opaque
|
|
478
|
+
// submeshes were drawn in the geometry pass.
|
|
479
|
+
if (submeshMaterial.transparent !== true) continue;
|
|
480
|
+
const smShaderId = submeshMaterial.materialShaderId;
|
|
481
|
+
if (smShaderId === undefined) continue;
|
|
482
|
+
|
|
483
|
+
// Bind the per-submesh material BG first (mirrors the geometry pass
|
|
484
|
+
// order), then resolve the PSO; a first-frame async-compile miss skips
|
|
485
|
+
// only the draw, not the BG (one transient frame, PSO flows in next).
|
|
486
|
+
const materialSlot = materialSlotIndices[i]?.[matSlotIdx] ?? materialSlotIndices[i]?.[0] ?? 0;
|
|
487
|
+
const subBg = resolveMaterialBindGroup(
|
|
488
|
+
materialSlot,
|
|
489
|
+
submeshMaterial,
|
|
490
|
+
entry.source.entityKey,
|
|
491
|
+
entry.world ?? c.world,
|
|
492
|
+
);
|
|
493
|
+
spritePass.setBindGroup(1, subBg, [materialSlot * MATERIAL_PER_ENTITY_STRIDE]);
|
|
494
|
+
|
|
495
|
+
const subPipeline =
|
|
496
|
+
runtime.getMaterialShaderPipeline?.(
|
|
497
|
+
smShaderId,
|
|
498
|
+
/* isHdr */ false,
|
|
499
|
+
submeshMaterial.renderState,
|
|
500
|
+
sm.topology,
|
|
501
|
+
entry.mesh.indexFormat,
|
|
502
|
+
projectionVariantSet,
|
|
503
|
+
'forward',
|
|
504
|
+
undefined,
|
|
505
|
+
sampleCount,
|
|
506
|
+
// Non-sRGB blend view (same override the sprite path uses).
|
|
507
|
+
transparentPassColorFormat(c) as GPUTextureFormat,
|
|
508
|
+
undefined,
|
|
509
|
+
undefined,
|
|
510
|
+
undefined,
|
|
511
|
+
entry.mesh.layoutProjection,
|
|
512
|
+
) ?? null;
|
|
513
|
+
if (subPipeline === null) continue;
|
|
514
|
+
|
|
515
|
+
if (lastPbrSubPipelineHandle !== subPipeline) {
|
|
516
|
+
spritePass.setPipeline(subPipeline);
|
|
517
|
+
lastPbrSubPipelineHandle = subPipeline;
|
|
518
|
+
}
|
|
519
|
+
if (entry.mesh.indexed) {
|
|
520
|
+
spritePass.drawIndexed(sm.indexCount, 1, sm.indexOffset, 0, 0);
|
|
521
|
+
} else {
|
|
522
|
+
spritePass.draw(sm.vertexCount, 1, 0, 0);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* feat-20260704 M3/w19: per-entity sprite / sprite-lit draw loop for the LDR
|
|
530
|
+
* blend sub-pass, extracted verbatim from the sprite split pass. Selects the
|
|
531
|
+
* sprite vs sprite-lit PSO per entity, resolves the per-entity / fold-bucket
|
|
532
|
+
* instance buffer (fold-instanced drawIndexed where a fold bucket applies and
|
|
533
|
+
* the entity has no explicit Instances), uploads the per-entity sprite material
|
|
534
|
+
* UBO slice, binds view / material / mesh / instances groups, and issues the
|
|
535
|
+
* draw. Non-sprite transparent submeshes are drawn separately
|
|
536
|
+
* (recordSpriteTransparentPbrDraws). The loop-invariant sprite PSO handles + the
|
|
537
|
+
* once-per-frame sprite-unavailable diagnostic are threaded in.
|
|
538
|
+
*
|
|
539
|
+
* @internal
|
|
540
|
+
*/
|
|
541
|
+
function recordSpriteEntityDraws(
|
|
542
|
+
c: _InternalRenderPipelineContext,
|
|
543
|
+
spritePass: RhiRenderPassEncoder,
|
|
544
|
+
matchedIndices: Set<number> | null,
|
|
545
|
+
skylightResources: SkylightBindGroupResources,
|
|
546
|
+
spritePH: RenderPipeline | null,
|
|
547
|
+
spritePH_withRegion: RenderPipeline | null,
|
|
548
|
+
spriteLitPH: RenderPipeline | null,
|
|
549
|
+
spriteUnavailable: boolean,
|
|
550
|
+
reportSpriteUnavailable: () => void,
|
|
551
|
+
): void {
|
|
552
|
+
const {
|
|
553
|
+
runtime,
|
|
554
|
+
world,
|
|
555
|
+
store,
|
|
556
|
+
pipelineState,
|
|
557
|
+
frameState,
|
|
558
|
+
bindGroupCounts,
|
|
559
|
+
validatedOrdered,
|
|
560
|
+
meshBindGroup,
|
|
561
|
+
foldDispatchPlan,
|
|
562
|
+
materialSlotIndices,
|
|
563
|
+
} = c;
|
|
564
|
+
let lastSpritePipelineHandle: RenderPipeline | null = null;
|
|
565
|
+
let lastSpriteVertexBuffer: GpuBuffer | null = null;
|
|
566
|
+
let lastSpriteIndexBuffer: GpuBuffer | null = null;
|
|
567
|
+
for (let i = 0; i < validatedOrdered.length; i++) {
|
|
568
|
+
const spriteEntry = validatedOrdered[i];
|
|
569
|
+
// feat-20260625 M3 / w13: sub-pass entity filter migrated from
|
|
570
|
+
// `shadingModel === 'sprite'` to `transparent === true` — the
|
|
571
|
+
// shadingModel arm is gone post-feat (plan-strategy D-3).
|
|
572
|
+
if (spriteEntry === undefined || spriteEntry.source.material.transparent !== true) continue;
|
|
573
|
+
// feat-city-glb Bug 5 (per-submesh transparency): this loop is the
|
|
574
|
+
// SPRITE path (whole-mesh sprite / sprite-lit PSO). Non-sprite
|
|
575
|
+
// transparent materials (built-in PBR, incl. glTF alphaMode=BLEND) are
|
|
576
|
+
// drawn per-submesh with their real shader in the dedicated PBR loop
|
|
577
|
+
// below — so skip them here. Previously the 4.3-blending window (a PBR
|
|
578
|
+
// material) was drawn through here with the sprite shader; it now flows
|
|
579
|
+
// through the PBR loop, which is both correct and multi-submesh-capable.
|
|
580
|
+
{
|
|
581
|
+
const sid = spriteEntry.source.material.materialShaderId;
|
|
582
|
+
const isSpriteShader = sid === 'forgeax::sprite' || sid === 'forgeax::sprite-lit';
|
|
583
|
+
if (!isSpriteShader) continue;
|
|
584
|
+
}
|
|
585
|
+
// Sprite PSO unavailable (sprite.wgsl absent / still compiling): skip
|
|
586
|
+
// sprite entities and report once, but do NOT abort the sub-pass — the
|
|
587
|
+
// PBR transparent loop below is independent of the sprite shader.
|
|
588
|
+
if (spriteUnavailable) {
|
|
589
|
+
reportSpriteUnavailable();
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// feat-20260622-chunk-gpu-instancing-sprite-tilemap M1 / w4-record-swap
|
|
594
|
+
// (D-1): fold-bucket non-head member — skip; the bucket head emits one
|
|
595
|
+
// instanced drawIndexed covering all members.
|
|
596
|
+
if (foldDispatchPlan?.skipIndices.has(i) === true) continue;
|
|
597
|
+
const foldHeadBucket = foldDispatchPlan?.headBuckets.get(i);
|
|
598
|
+
|
|
599
|
+
// feat-20260609 M2: skip entities that don't match the pass selector.
|
|
600
|
+
if (matchedIndices !== null && !matchedIndices.has(spriteEntry.renderableIndex)) continue;
|
|
601
|
+
|
|
602
|
+
// feat-20260624 M1' / t7: select sprite vs sprite-lit PSO per
|
|
603
|
+
// entity. Both paths share the LDR sub-pass + the same UBO
|
|
604
|
+
// layout; only the shader module + fragment math differ. PSO
|
|
605
|
+
// cache strings are isolated by materialShaderId (D-11) so
|
|
606
|
+
// routing here keeps the cache slots disjoint.
|
|
607
|
+
//
|
|
608
|
+
// bug-20260629: SpriteInstances entities additionally need the
|
|
609
|
+
// PER_INSTANCE_REGION=true variant so the shader reads UV region
|
|
610
|
+
// from the 80B-per-instance interleaved buffer rather than from
|
|
611
|
+
// the material UBO. Only the base sprite path has the per-instance
|
|
612
|
+
// region variant compiled; sprite-lit + non-instances entities
|
|
613
|
+
// keep the PER_INSTANCE_REGION=false variant.
|
|
614
|
+
const entityShaderId = spriteEntry.source.material.materialShaderId;
|
|
615
|
+
const useRegionVariant =
|
|
616
|
+
entityShaderId !== 'forgeax::sprite-lit' && spriteEntry.source.spriteInstances !== undefined;
|
|
617
|
+
const activeSpritePH =
|
|
618
|
+
entityShaderId === 'forgeax::sprite-lit'
|
|
619
|
+
? spriteLitPH
|
|
620
|
+
: useRegionVariant
|
|
621
|
+
? spritePH_withRegion
|
|
622
|
+
: spritePH;
|
|
623
|
+
if (activeSpritePH === null) {
|
|
624
|
+
// Variant not yet compiled — for PER_INSTANCE_REGION=true the
|
|
625
|
+
// variant cache fill is async on first use (mirrors the
|
|
626
|
+
// spritePH===null guard above); falling back to the non-region
|
|
627
|
+
// variant would render black quads (region read returns 0).
|
|
628
|
+
// For sprite-lit the manifest may lack sprite-lit.wgsl; either
|
|
629
|
+
// way fail-safe-skip is the closest the renderer can get to
|
|
630
|
+
// "show nothing visibly wrong" without ending the sprite pass
|
|
631
|
+
// (which would drop remaining sprite entities for the frame).
|
|
632
|
+
if (entityShaderId === 'forgeax::sprite-lit') {
|
|
633
|
+
runtime.errorRegistry.fire(
|
|
634
|
+
new RhiError({
|
|
635
|
+
code: 'shader-compile-failed',
|
|
636
|
+
expected:
|
|
637
|
+
'manifest entries include sprite.wgsl + sprite-lit.wgsl (when sprite-lit materials are used) + the engine triple (pbr + unlit + tonemap)',
|
|
638
|
+
hint: 'verify @forgeax/engine-vite-plugin-shader emits manifest.json with sprite.wgsl AND sprite-lit.wgsl entries; check vite plugin engineEntries option',
|
|
639
|
+
}),
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
if (lastSpritePipelineHandle !== activeSpritePH) {
|
|
645
|
+
spritePass.setPipeline(activeSpritePH);
|
|
646
|
+
lastSpritePipelineHandle = activeSpritePH;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (spriteEntry.mesh.vertexBuffer !== lastSpriteVertexBuffer) {
|
|
650
|
+
spritePass.setVertexBuffer(0, spriteEntry.mesh.vertexBuffer.handle);
|
|
651
|
+
lastSpriteVertexBuffer = spriteEntry.mesh.vertexBuffer;
|
|
652
|
+
}
|
|
653
|
+
if (
|
|
654
|
+
spriteEntry.mesh.indexBuffer !== null &&
|
|
655
|
+
spriteEntry.mesh.indexBuffer !== lastSpriteIndexBuffer
|
|
656
|
+
) {
|
|
657
|
+
spritePass.setIndexBuffer(spriteEntry.mesh.indexBuffer.handle, spriteEntry.mesh.indexFormat);
|
|
658
|
+
lastSpriteIndexBuffer = spriteEntry.mesh.indexBuffer;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// Instance buffer resolution: same cap-gate logic as the geometry
|
|
662
|
+
// pass entity loop; sprites with Instances (e.g. hello-sprite-atlas
|
|
663
|
+
// 100-instance walk-cycle) require per-entity storage buffer upload.
|
|
664
|
+
// SSOT mirror of geometry pass instances block above (~line 1610):
|
|
665
|
+
// identical cap-gate sequence (storageBuffer cap → limit-exceeded →
|
|
666
|
+
// cache-lookup → createBuffer → writeBuffer); variable names carry
|
|
667
|
+
// "sprite" prefix; logic divergence would be a bug.
|
|
668
|
+
//
|
|
669
|
+
// feat-20260622-chunk-gpu-instancing-sprite-tilemap M1 / w4-record-swap
|
|
670
|
+
// (D-1): when `foldHeadBucket !== undefined` AND the sprite entity has
|
|
671
|
+
// no explicit Instances component, assemble the bucket transforms into
|
|
672
|
+
// a transient instance buffer + override `spriteInstanceCount =
|
|
673
|
+
// bucket.bucketSize`. The mesh slot at `i*MESH_PER_ENTITY_STRIDE` was
|
|
674
|
+
// already overwritten to identity in the mesh SSBO upload loop above,
|
|
675
|
+
// so the shader computes `world = identity * bucket.transforms[idx] *
|
|
676
|
+
// pos`, per-instance correct. Entities with explicit Instances bypass
|
|
677
|
+
// fold (their per-entity Instances semantic wins); bucket key forces
|
|
678
|
+
// such an entity to be a singleton bucket in practice because its
|
|
679
|
+
// material is distinct or unfolded, but defensively check here as a
|
|
680
|
+
// belt-and-suspenders guard.
|
|
681
|
+
let spriteInstanceBuffer: Buffer = pipelineState.identityInstanceBuffer;
|
|
682
|
+
let spriteInstanceCount = 1;
|
|
683
|
+
const spriteInst = spriteEntry.source.instances;
|
|
684
|
+
const useFold = foldHeadBucket !== undefined && spriteInst === undefined;
|
|
685
|
+
if (useFold && foldHeadBucket !== undefined) {
|
|
686
|
+
// w6 (D-8): bucket transient buffer reuse — composite cacheKey from
|
|
687
|
+
// (materialHandle, layer, validatedOrdered head index) so the
|
|
688
|
+
// existing `frameState.instanceBuffers` byteLength/archVersion path
|
|
689
|
+
// covers static steady-state upload-skip. Numeric Map<number,…> key
|
|
690
|
+
// requires a 32-bit-safe fold; we use a negative number-space prefix
|
|
691
|
+
// (-1, -2, ...) by `((materialHandle << 16) | i)` shifted into the
|
|
692
|
+
// negative half so it never collides with positive entity-Instances
|
|
693
|
+
// cacheKeys (which are extracted from Instances component cacheKey
|
|
694
|
+
// numeric ids, always non-negative). The `archVersion` proxy is
|
|
695
|
+
// bucketSize (a structural-shape signal) so static frames hit the
|
|
696
|
+
// cache.
|
|
697
|
+
const bucketCacheKey = -1 - (((foldHeadBucket.materialHandle & 0xffff) << 16) | (i & 0xffff));
|
|
698
|
+
const uniformFallback = runtime.device.caps.storageBuffer === false;
|
|
699
|
+
const bucketPayload = uniformFallback
|
|
700
|
+
? foldHeadBucket.transforms
|
|
701
|
+
: packInstanceStorageBuffer(foldHeadBucket.transforms);
|
|
702
|
+
const bucketBytes = bucketPayload.byteLength;
|
|
703
|
+
const bucketBufUsage = uniformFallback
|
|
704
|
+
? GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST
|
|
705
|
+
: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
|
|
706
|
+
const cachedBucket = frameState.instanceBuffers.get(bucketCacheKey);
|
|
707
|
+
let activeBucket: InstanceBufferCacheEntry | null = null;
|
|
708
|
+
if (
|
|
709
|
+
cachedBucket !== undefined &&
|
|
710
|
+
cachedBucket.uploadedArchVersion === foldHeadBucket.bucketSize &&
|
|
711
|
+
cachedBucket.uploadedByteLength === bucketBytes
|
|
712
|
+
) {
|
|
713
|
+
activeBucket = cachedBucket;
|
|
714
|
+
} else if (bucketBytes > 0) {
|
|
715
|
+
const bufRes = runtime.device.createBuffer({
|
|
716
|
+
size: bucketBytes,
|
|
717
|
+
usage: bucketBufUsage,
|
|
718
|
+
mappedAtCreation: false,
|
|
719
|
+
});
|
|
720
|
+
if (!bufRes.ok) {
|
|
721
|
+
runtime.errorRegistry.fire(bufRes.error);
|
|
722
|
+
} else {
|
|
723
|
+
if (cachedBucket !== undefined && !cachedBucket.buffer.isDestroyed) {
|
|
724
|
+
const r = cachedBucket.buffer.destroy();
|
|
725
|
+
if (!r.ok) runtime.errorRegistry.fire(r.error);
|
|
726
|
+
}
|
|
727
|
+
const newBuf = new GpuBuffer(runtime.device, bufRes.value);
|
|
728
|
+
activeBucket = {
|
|
729
|
+
buffer: newBuf,
|
|
730
|
+
uploadedArchVersion: foldHeadBucket.bucketSize,
|
|
731
|
+
uploadedByteLength: bucketBytes,
|
|
732
|
+
};
|
|
733
|
+
frameState.instanceBuffers.set(bucketCacheKey, activeBucket);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
if (activeBucket !== null) {
|
|
737
|
+
const writeRes = runtime.device.queue.writeBuffer(
|
|
738
|
+
activeBucket.buffer.handle,
|
|
739
|
+
0,
|
|
740
|
+
bucketPayload,
|
|
741
|
+
);
|
|
742
|
+
if (!writeRes.ok) {
|
|
743
|
+
runtime.errorRegistry.fire(writeRes.error);
|
|
744
|
+
} else {
|
|
745
|
+
spriteInstanceBuffer = activeBucket.buffer.handle;
|
|
746
|
+
spriteInstanceCount = foldHeadBucket.bucketSize;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
} else if (spriteInst !== undefined) {
|
|
750
|
+
const uniformFallback = runtime.device.caps.storageBuffer === false;
|
|
751
|
+
let spriteBufUsage = GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST;
|
|
752
|
+
|
|
753
|
+
if (uniformFallback) {
|
|
754
|
+
if (spriteInst.instanceCount > MAX_UNIFORM_INSTANCES) {
|
|
755
|
+
runtime.errorRegistry.fire(
|
|
756
|
+
new RhiError({
|
|
757
|
+
code: 'limit-exceeded',
|
|
758
|
+
expected: `instance count <= ${MAX_UNIFORM_INSTANCES} (uniform fallback cap)`,
|
|
759
|
+
hint: `reduce instance count to ${MAX_UNIFORM_INSTANCES} or use a WebGPU-capable backend`,
|
|
760
|
+
detail: {
|
|
761
|
+
maxStorageBufferBindingSize: MAX_UNIFORM_INSTANCES * 64,
|
|
762
|
+
requestedBytes: spriteInst.instanceCount * 64,
|
|
763
|
+
},
|
|
764
|
+
}),
|
|
765
|
+
);
|
|
766
|
+
spriteInstanceCount = spriteInst.instanceCount;
|
|
767
|
+
spriteInstanceBuffer = pipelineState.identityInstanceBuffer;
|
|
768
|
+
const spriteInstBgResult = runtime.device.createBindGroup({
|
|
769
|
+
label: 'sprite-pass-instances-bg',
|
|
770
|
+
layout: pipelineState.instancesBindGroupLayout,
|
|
771
|
+
entries: [
|
|
772
|
+
{
|
|
773
|
+
binding: 0,
|
|
774
|
+
resource: {
|
|
775
|
+
kind: 'buffer',
|
|
776
|
+
value: { buffer: spriteInstanceBuffer },
|
|
777
|
+
},
|
|
778
|
+
},
|
|
779
|
+
],
|
|
780
|
+
});
|
|
781
|
+
if (!spriteInstBgResult.ok) throw spriteInstBgResult.error;
|
|
782
|
+
spritePass.setBindGroup(3, spriteInstBgResult.value as BindGroup);
|
|
783
|
+
spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
spriteBufUsage = GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
{
|
|
790
|
+
const instancePayload = uniformFallback
|
|
791
|
+
? spriteInst.transforms
|
|
792
|
+
: packInstanceStorageBuffer(spriteInst.transforms);
|
|
793
|
+
const requestedBytes = instancePayload.byteLength;
|
|
794
|
+
const cap = runtime.device.limits.maxStorageBufferBindingSize;
|
|
795
|
+
if (typeof cap === 'number' && requestedBytes > cap) {
|
|
796
|
+
runtime.errorRegistry.fire(
|
|
797
|
+
new RhiError({
|
|
798
|
+
code: 'limit-exceeded',
|
|
799
|
+
expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
|
|
800
|
+
hint: 'reduce instance count to fit within device.limits.maxStorageBufferBindingSize, or split transforms across multiple Instances entries',
|
|
801
|
+
detail: {
|
|
802
|
+
maxStorageBufferBindingSize: cap,
|
|
803
|
+
requestedBytes,
|
|
804
|
+
},
|
|
805
|
+
}),
|
|
806
|
+
);
|
|
807
|
+
} else {
|
|
808
|
+
const cachedSprite = frameState.instanceBuffers.get(
|
|
809
|
+
worldEntityKey(spriteEntry.source.worldId, spriteInst.cacheKey),
|
|
810
|
+
);
|
|
811
|
+
let activeSprite: InstanceBufferCacheEntry | null = null;
|
|
812
|
+
if (
|
|
813
|
+
cachedSprite !== undefined &&
|
|
814
|
+
cachedSprite.uploadedArchVersion === spriteInst.archVersion &&
|
|
815
|
+
cachedSprite.uploadedByteLength === requestedBytes
|
|
816
|
+
) {
|
|
817
|
+
activeSprite = cachedSprite;
|
|
818
|
+
} else if (requestedBytes > 0) {
|
|
819
|
+
const bufRes = runtime.device.createBuffer({
|
|
820
|
+
size: requestedBytes,
|
|
821
|
+
usage: spriteBufUsage,
|
|
822
|
+
mappedAtCreation: false,
|
|
823
|
+
});
|
|
824
|
+
if (!bufRes.ok) {
|
|
825
|
+
runtime.errorRegistry.fire(bufRes.error);
|
|
826
|
+
} else {
|
|
827
|
+
// feat-20260619 M4 / F12: destroy the old cached buffer
|
|
828
|
+
// before replacing it with the new one (D-6).
|
|
829
|
+
if (cachedSprite !== undefined && !cachedSprite.buffer.isDestroyed) {
|
|
830
|
+
const r = cachedSprite.buffer.destroy();
|
|
831
|
+
if (!r.ok) runtime.errorRegistry.fire(r.error);
|
|
832
|
+
}
|
|
833
|
+
const newBuf = new GpuBuffer(runtime.device, bufRes.value);
|
|
834
|
+
activeSprite = {
|
|
835
|
+
buffer: newBuf,
|
|
836
|
+
uploadedArchVersion: spriteInst.archVersion,
|
|
837
|
+
uploadedByteLength: requestedBytes,
|
|
838
|
+
};
|
|
839
|
+
frameState.instanceBuffers.set(
|
|
840
|
+
worldEntityKey(spriteEntry.source.worldId, spriteInst.cacheKey),
|
|
841
|
+
activeSprite,
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
if (activeSprite !== null) {
|
|
846
|
+
const writeRes = runtime.device.queue.writeBuffer(
|
|
847
|
+
activeSprite.buffer.handle,
|
|
848
|
+
0,
|
|
849
|
+
instancePayload,
|
|
850
|
+
);
|
|
851
|
+
if (!writeRes.ok) {
|
|
852
|
+
runtime.errorRegistry.fire(writeRes.error);
|
|
853
|
+
} else {
|
|
854
|
+
spriteInstanceBuffer = activeSprite.buffer.handle;
|
|
855
|
+
spriteInstanceCount = Math.max(1, spriteInst.instanceCount);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// feat-20260625-sprite-instances-and-tilemap-terrain-static-batch
|
|
863
|
+
// M3 / w11: SpriteInstances 80B-per-instance interleaved upload path.
|
|
864
|
+
// SSOT for the per-entity 2D mat4 + per-instance UV region buffer
|
|
865
|
+
// (plan-strategy D-1 interleaved single buffer + single binding slot;
|
|
866
|
+
// D-9 cacheKey = entity packed u32). The extract-stage validator
|
|
867
|
+
// (M3 / w10) enforces the XOR contract `Instances XOR SpriteInstances`
|
|
868
|
+
// (sprite-instances-mutually-exclusive-with-instances), so the
|
|
869
|
+
// legacy `spriteInst` block above and this block are never both
|
|
870
|
+
// active for the same entity.
|
|
871
|
+
const _si = resolveSpriteInstancesBuffer(
|
|
872
|
+
c,
|
|
873
|
+
spriteEntry,
|
|
874
|
+
spriteInstanceBuffer,
|
|
875
|
+
spriteInstanceCount,
|
|
876
|
+
);
|
|
877
|
+
spriteInstanceBuffer = _si.buffer;
|
|
878
|
+
spriteInstanceCount = _si.count;
|
|
879
|
+
|
|
880
|
+
// M3 / w12: LDR sprite split pass per-entity instances BG cache.
|
|
881
|
+
// Same pattern as #7.
|
|
882
|
+
const spriteInstancesBg: BindGroup = getOrCreatePerEntity(
|
|
883
|
+
frameState.instancesBgPerEntity,
|
|
884
|
+
worldEntityKey(spriteEntry.source.worldId, spriteEntry.source.entityKey),
|
|
885
|
+
[spriteInstanceBuffer],
|
|
886
|
+
'instances',
|
|
887
|
+
() => {
|
|
888
|
+
const result = runtime.device.createBindGroup({
|
|
889
|
+
label: 'sprite-pass-instances-bg',
|
|
890
|
+
layout: pipelineState.instancesBindGroupLayout,
|
|
891
|
+
entries: [
|
|
892
|
+
{
|
|
893
|
+
binding: 0,
|
|
894
|
+
resource: {
|
|
895
|
+
kind: 'buffer',
|
|
896
|
+
value: { buffer: spriteInstanceBuffer },
|
|
897
|
+
},
|
|
898
|
+
},
|
|
899
|
+
],
|
|
900
|
+
});
|
|
901
|
+
if (!result.ok) throw result.error;
|
|
902
|
+
return result.value;
|
|
903
|
+
},
|
|
904
|
+
bindGroupCounts,
|
|
905
|
+
);
|
|
906
|
+
|
|
907
|
+
spritePass.setBindGroup(2, meshBindGroup as BindGroup, [i * MESH_PER_ENTITY_STRIDE]);
|
|
908
|
+
|
|
909
|
+
// Per-entity sprite material bind group: same standard PBR user-region
|
|
910
|
+
// layout as in the geometry pass sprite branch + Skylight merged entries
|
|
911
|
+
// the geometry pass sprite branch + Skylight merged entries (same
|
|
912
|
+
// skylightResources in scope from above). Texture view is resolved
|
|
913
|
+
// from the sprite material's baseColorTexture handle.
|
|
914
|
+
const spriteTexHandle = spriteEntry.source.material.baseColorTexture as
|
|
915
|
+
| Handle<'TextureAsset', 'shared'>
|
|
916
|
+
| undefined;
|
|
917
|
+
let spriteTexView = pipelineState.defaultWhiteTextureView;
|
|
918
|
+
if (spriteTexHandle !== undefined) {
|
|
919
|
+
const tv = residentTextureView(spriteEntry.world ?? world, store, runtime, spriteTexHandle);
|
|
920
|
+
if (tv !== undefined) spriteTexView = tv as never;
|
|
921
|
+
}
|
|
922
|
+
const spritePassBaseMaterialEntries = [
|
|
923
|
+
{
|
|
924
|
+
binding: 0,
|
|
925
|
+
resource: {
|
|
926
|
+
kind: 'buffer' as const,
|
|
927
|
+
value: {
|
|
928
|
+
buffer: pipelineState.materialUniformBuffer.buffer,
|
|
929
|
+
offset: 0,
|
|
930
|
+
size: STANDARD_PBR_UBO_SIZE,
|
|
931
|
+
},
|
|
932
|
+
},
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
binding: 1,
|
|
936
|
+
resource: { kind: 'sampler' as const, value: pipelineState.nearestSampler },
|
|
937
|
+
},
|
|
938
|
+
{ binding: 2, resource: { kind: 'textureView' as const, value: spriteTexView } },
|
|
939
|
+
{
|
|
940
|
+
binding: 3,
|
|
941
|
+
resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
binding: 4,
|
|
945
|
+
resource: {
|
|
946
|
+
kind: 'textureView' as const,
|
|
947
|
+
value: pipelineState.defaultWhiteTextureView,
|
|
948
|
+
},
|
|
949
|
+
},
|
|
950
|
+
{
|
|
951
|
+
binding: 5,
|
|
952
|
+
resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
binding: 6,
|
|
956
|
+
resource: {
|
|
957
|
+
kind: 'textureView' as const,
|
|
958
|
+
value: pipelineState.defaultNormalTextureView,
|
|
959
|
+
},
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
binding: 7,
|
|
963
|
+
resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
|
|
964
|
+
},
|
|
965
|
+
{
|
|
966
|
+
binding: 8,
|
|
967
|
+
resource: {
|
|
968
|
+
kind: 'textureView' as const,
|
|
969
|
+
value: pipelineState.defaultWhiteTextureView,
|
|
970
|
+
},
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
binding: 9,
|
|
974
|
+
resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
|
|
975
|
+
},
|
|
976
|
+
{
|
|
977
|
+
binding: 10,
|
|
978
|
+
resource: {
|
|
979
|
+
kind: 'textureView' as const,
|
|
980
|
+
value: pipelineState.defaultWhiteTextureView,
|
|
981
|
+
},
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
binding: 11,
|
|
985
|
+
resource: { kind: 'sampler' as const, value: pipelineState.defaultSampler },
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
binding: 12,
|
|
989
|
+
resource: {
|
|
990
|
+
kind: 'textureView' as const,
|
|
991
|
+
value: pipelineState.defaultWhiteTextureView,
|
|
992
|
+
},
|
|
993
|
+
},
|
|
994
|
+
];
|
|
995
|
+
const spritePassEmissiveAo: EmissiveAoBindGroupResources = {
|
|
996
|
+
emissiveSampler: pipelineState.defaultSampler,
|
|
997
|
+
emissiveView: pipelineState.defaultWhiteTextureView,
|
|
998
|
+
occlusionSampler: pipelineState.defaultSampler,
|
|
999
|
+
occlusionView: pipelineState.defaultWhiteTextureView,
|
|
1000
|
+
};
|
|
1001
|
+
const spritePassMergedEntries = assembleMaterialWithSkylightEntries(
|
|
1002
|
+
spritePassBaseMaterialEntries,
|
|
1003
|
+
skylightResources,
|
|
1004
|
+
spritePassEmissiveAo,
|
|
1005
|
+
);
|
|
1006
|
+
|
|
1007
|
+
// Sprite-pass material BG cache: keyed on shader id (shared across all
|
|
1008
|
+
// sprite entities) so entities using the same atlas texture share one
|
|
1009
|
+
// BindGroup instead of creating one per entity (O5 fix — inner WeakMap
|
|
1010
|
+
// chain naturally deduplicates by GPU resource object identity, so two
|
|
1011
|
+
// entities with different atlases still get distinct BGs).
|
|
1012
|
+
const spritePassBg: BindGroup = getOrCreatePerEntity(
|
|
1013
|
+
frameState.materialBgShared,
|
|
1014
|
+
'forgeax::sprite',
|
|
1015
|
+
spritePassMergedEntries.map((e) => extractEntryResourceHandle(e)),
|
|
1016
|
+
'sprite-pass-material',
|
|
1017
|
+
() => {
|
|
1018
|
+
const result = runtime.device.createBindGroup({
|
|
1019
|
+
label: 'sprite-pass-material-bg',
|
|
1020
|
+
layout: pipelineState.materialBindGroupLayout,
|
|
1021
|
+
entries: spritePassMergedEntries,
|
|
1022
|
+
});
|
|
1023
|
+
if (!result.ok) throw result.error;
|
|
1024
|
+
return result.value;
|
|
1025
|
+
},
|
|
1026
|
+
bindGroupCounts,
|
|
1027
|
+
);
|
|
1028
|
+
|
|
1029
|
+
const materialSlot = materialSlotIndices[i]?.[0] ?? 0;
|
|
1030
|
+
spritePass.setBindGroup(1, spritePassBg, [materialSlot * MATERIAL_PER_ENTITY_STRIDE]);
|
|
1031
|
+
spritePass.setBindGroup(3, spriteInstancesBg);
|
|
1032
|
+
spritePass.drawIndexed(spriteEntry.mesh.indexCount, spriteInstanceCount, 0, 0, 0);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* feat-20260704 M3/w19: resolve the interleaved SpriteInstances (@group(3))
|
|
1038
|
+
* buffer + instanceCount for a sprite entity in the LDR blend sub-pass,
|
|
1039
|
+
* extracted verbatim from recordSpriteEntityDraws. Uploads the interleaved
|
|
1040
|
+
* mat4 + per-instance UV region transforms (cache-keyed on the snapshot); on
|
|
1041
|
+
* over-cap fires the structured limit-exceeded error and leaves the passed-in
|
|
1042
|
+
* fallback buffer/count. Returns the resolved (or unchanged) buffer + count.
|
|
1043
|
+
*
|
|
1044
|
+
* @internal
|
|
1045
|
+
*/
|
|
1046
|
+
function resolveSpriteInstancesBuffer(
|
|
1047
|
+
c: _InternalRenderPipelineContext,
|
|
1048
|
+
spriteEntry: _InternalRenderPipelineContext['validatedOrdered'][number],
|
|
1049
|
+
fallbackBuffer: Buffer,
|
|
1050
|
+
fallbackCount: number,
|
|
1051
|
+
): { buffer: Buffer; count: number } {
|
|
1052
|
+
const { runtime, frameState } = c;
|
|
1053
|
+
let buffer = fallbackBuffer;
|
|
1054
|
+
let count = fallbackCount;
|
|
1055
|
+
const spriteInstancesSnap: SpriteInstancesSnapshot | undefined =
|
|
1056
|
+
spriteEntry.source.spriteInstances;
|
|
1057
|
+
if (spriteInstancesSnap !== undefined) {
|
|
1058
|
+
const uniformFallback = runtime.device.caps.storageBuffer === false;
|
|
1059
|
+
const interleaved = interleaveSpriteInstanceBuffer(
|
|
1060
|
+
spriteInstancesSnap.transforms,
|
|
1061
|
+
spriteInstancesSnap.regions,
|
|
1062
|
+
!uniformFallback,
|
|
1063
|
+
);
|
|
1064
|
+
const requestedBytes = interleaved.byteLength;
|
|
1065
|
+
const cap = runtime.device.limits.maxStorageBufferBindingSize;
|
|
1066
|
+
if (typeof cap === 'number' && requestedBytes > cap) {
|
|
1067
|
+
runtime.errorRegistry.fire(
|
|
1068
|
+
new RhiError({
|
|
1069
|
+
code: 'limit-exceeded',
|
|
1070
|
+
expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
|
|
1071
|
+
hint: 'reduce SpriteInstances instance count to fit within device.limits.maxStorageBufferBindingSize (144 bytes per instance: current mat4 64B + previous mat4 64B + region 16B)',
|
|
1072
|
+
detail: {
|
|
1073
|
+
maxStorageBufferBindingSize: cap,
|
|
1074
|
+
requestedBytes,
|
|
1075
|
+
},
|
|
1076
|
+
}),
|
|
1077
|
+
);
|
|
1078
|
+
} else {
|
|
1079
|
+
const cachedSpriteInst = frameState.instanceBuffers.get(
|
|
1080
|
+
worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
|
|
1081
|
+
);
|
|
1082
|
+
let activeSpriteInst: InstanceBufferCacheEntry | null = null;
|
|
1083
|
+
if (spriteInstancesCacheHit(cachedSpriteInst, spriteInstancesSnap, requestedBytes)) {
|
|
1084
|
+
activeSpriteInst = cachedSpriteInst ?? null;
|
|
1085
|
+
} else if (requestedBytes > 0) {
|
|
1086
|
+
const bufRes = runtime.device.createBuffer({
|
|
1087
|
+
size: requestedBytes,
|
|
1088
|
+
usage:
|
|
1089
|
+
(uniformFallback ? GPU_BUFFER_USAGE_UNIFORM : GPU_BUFFER_USAGE_STORAGE) |
|
|
1090
|
+
GPU_BUFFER_USAGE_COPY_DST,
|
|
1091
|
+
mappedAtCreation: false,
|
|
1092
|
+
});
|
|
1093
|
+
if (!bufRes.ok) {
|
|
1094
|
+
runtime.errorRegistry.fire(bufRes.error);
|
|
1095
|
+
} else {
|
|
1096
|
+
if (cachedSpriteInst !== undefined && !cachedSpriteInst.buffer.isDestroyed) {
|
|
1097
|
+
const r = cachedSpriteInst.buffer.destroy();
|
|
1098
|
+
if (!r.ok) runtime.errorRegistry.fire(r.error);
|
|
1099
|
+
}
|
|
1100
|
+
const newBuf = new GpuBuffer(runtime.device, bufRes.value);
|
|
1101
|
+
activeSpriteInst = {
|
|
1102
|
+
buffer: newBuf,
|
|
1103
|
+
uploadedArchVersion: spriteInstancesSnap.archVersion,
|
|
1104
|
+
uploadedByteLength: requestedBytes,
|
|
1105
|
+
};
|
|
1106
|
+
frameState.instanceBuffers.set(
|
|
1107
|
+
worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
|
|
1108
|
+
activeSpriteInst,
|
|
1109
|
+
);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
if (activeSpriteInst !== null && requestedBytes > 0) {
|
|
1113
|
+
const writeRes = runtime.device.queue.writeBuffer(
|
|
1114
|
+
activeSpriteInst.buffer.handle,
|
|
1115
|
+
0,
|
|
1116
|
+
interleaved,
|
|
1117
|
+
);
|
|
1118
|
+
if (!writeRes.ok) {
|
|
1119
|
+
runtime.errorRegistry.fire(writeRes.error);
|
|
1120
|
+
} else {
|
|
1121
|
+
buffer = activeSpriteInst.buffer.handle;
|
|
1122
|
+
count = spriteInstancesSnap.instanceCount;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
return { buffer, count };
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
function transparentPassColorFormat(
|
|
1131
|
+
c: _InternalRenderPipelineContext,
|
|
1132
|
+
pipelineState: _InternalRenderPipelineContext['pipelineState'] = c.pipelineState,
|
|
1133
|
+
): string {
|
|
1134
|
+
if (c.transparentColorFormat !== undefined) return c.transparentColorFormat;
|
|
1135
|
+
if (!c.runtime.device.caps.storageBuffer) return pipelineState.colorAttachmentFormat;
|
|
1136
|
+
return pipelineState.format;
|
|
1137
|
+
}
|