@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,1043 @@
|
|
|
1
|
+
// @forgeax/engine-runtime - RenderSystem record stage: main-pass-material.
|
|
2
|
+
// Extracted from render-system-record.ts (feat-20260704 M3/w17, pure move).
|
|
3
|
+
|
|
4
|
+
import { resolveAssetHandle } from '@forgeax/engine-assets-runtime';
|
|
5
|
+
import type { EntityHandle, World } from '@forgeax/engine-ecs';
|
|
6
|
+
import {
|
|
7
|
+
VIDEO_ELEMENT_PROVIDER_KEY,
|
|
8
|
+
type VideoElementProvider,
|
|
9
|
+
} from '@forgeax/engine-graphics-extras';
|
|
10
|
+
import {
|
|
11
|
+
type BindGroup,
|
|
12
|
+
type BindGroupEntry,
|
|
13
|
+
type BindGroupLayout,
|
|
14
|
+
type Buffer,
|
|
15
|
+
type RenderPipeline,
|
|
16
|
+
RhiError,
|
|
17
|
+
type Sampler,
|
|
18
|
+
type TextureView,
|
|
19
|
+
} from '@forgeax/engine-rhi';
|
|
20
|
+
import {
|
|
21
|
+
DEFAULT_MSDF_TEXT_PARAM_SCHEMA,
|
|
22
|
+
DEFAULT_SPRITE_PARAM_SCHEMA,
|
|
23
|
+
DEFAULT_UNLIT_PARAM_SCHEMA,
|
|
24
|
+
} from '@forgeax/engine-shader';
|
|
25
|
+
import type {
|
|
26
|
+
Handle,
|
|
27
|
+
ImageError,
|
|
28
|
+
MaterialRenderState,
|
|
29
|
+
ParamSchemaEntry,
|
|
30
|
+
PrimitiveTopology,
|
|
31
|
+
SamplerAsset,
|
|
32
|
+
TextureAsset,
|
|
33
|
+
} from '@forgeax/engine-types';
|
|
34
|
+
import { derive, handleSlot, resolveMaterialTextureCoordinates } from '@forgeax/engine-types';
|
|
35
|
+
import type { GpuResidencyCache } from '../device/gpu-residency';
|
|
36
|
+
import { VideoUploadUnsupportedError } from '../errors/render';
|
|
37
|
+
import {
|
|
38
|
+
assembleMaterialWithSkylightEntries,
|
|
39
|
+
type EmissiveAoBindGroupResources,
|
|
40
|
+
type SkylightBindGroupResources,
|
|
41
|
+
} from '../ibl/skylight-bind-group';
|
|
42
|
+
import { isStandardPbrMaterialShader } from '../pbr-pipeline';
|
|
43
|
+
import { deriveTextureExtent } from '../render-data';
|
|
44
|
+
import type { MaterialSnapshot } from '../render-system-extract';
|
|
45
|
+
import type { BindGroupCounts, MaterialBgAssemblyCacheEntry } from './frame-snapshot';
|
|
46
|
+
import { extractEntryResourceHandle, getOrCreatePerEntity } from './mesh-ssbo';
|
|
47
|
+
import {
|
|
48
|
+
type PipelineState,
|
|
49
|
+
type RenderSystemRuntime,
|
|
50
|
+
STANDARD_PBR_UBO_SIZE,
|
|
51
|
+
} from './render-context';
|
|
52
|
+
|
|
53
|
+
// Param schemas are immutable runtime contracts: the shader registry installs
|
|
54
|
+
// them once and material snapshots only retain the same array reference. Keep
|
|
55
|
+
// the expensive pure derivation on that identity so the per-submesh record
|
|
56
|
+
// path does not rebuild the same UBO/texture maps for every visible material
|
|
57
|
+
// on every frame. A WeakMap keeps this optimization bounded by the lifetime of
|
|
58
|
+
// the schema owner and adds no global strong-reference lifetime.
|
|
59
|
+
const DERIVED_PARAM_SCHEMA_CACHE = new WeakMap<
|
|
60
|
+
readonly ParamSchemaEntry[],
|
|
61
|
+
ReturnType<typeof derive>
|
|
62
|
+
>();
|
|
63
|
+
|
|
64
|
+
function derivedParamSchema(schema: readonly ParamSchemaEntry[]): ReturnType<typeof derive> {
|
|
65
|
+
const cached = DERIVED_PARAM_SCHEMA_CACHE.get(schema);
|
|
66
|
+
if (cached !== undefined) return cached;
|
|
67
|
+
const derived = derive(schema);
|
|
68
|
+
DERIVED_PARAM_SCHEMA_CACHE.set(schema, derived);
|
|
69
|
+
return derived;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// feat-20260601-customizable-render-pipeline-seam M2 / w12: the former
|
|
73
|
+
// `RecordPassContext` (26-field full surface, including the `internals` kitchen-sink and
|
|
74
|
+
// the 0-consumed `skyboxCount` residual) is DELETED. The per-frame shared state injected
|
|
75
|
+
// into the render-graph pass execute closures is now the clean `RenderPipelineContext`
|
|
76
|
+
// (defined in `render-system.ts`): `internals` is gone (replaced by the named
|
|
77
|
+
// `assets` / `store` / `pipelineState` / `runtime` surfaces) so a pipeline author cannot
|
|
78
|
+
// reach the runtime kitchen-sink through the public ctx (AC-08). The graph is
|
|
79
|
+
// `RenderGraph<RenderPipelineContext>` so `execute(ctx)` forwards the object to each
|
|
80
|
+
// closure with no `as` assertion.
|
|
81
|
+
//
|
|
82
|
+
// Encoder ownership (RD-4): `ctx.encoder` is the SHARED frame encoder used by the main /
|
|
83
|
+
// tonemap / FXAA passes (finished + submitted once at frame end); the shadow pass opens
|
|
84
|
+
// its OWN encoder internally + submits independently (the runtime-side manual barrier for
|
|
85
|
+
// the depth write -> sample hazard).
|
|
86
|
+
|
|
87
|
+
// M1 / w7: ensureLazyTexture DELETED — GPU texture ownership moved to render-graph
|
|
88
|
+
// via addColorTarget + compile(device). The graph allocates transient/persistent
|
|
89
|
+
// render targets during the compile allocation phase; pass execute closures resolve
|
|
90
|
+
// TextureViews through resolve(name). PerPassResources texture slots still hold
|
|
91
|
+
// the last-used views for bindgroup-invalidation self-checks (D-3 physical texture
|
|
92
|
+
// identity), but the graph owns the create/destroy lifecycle.
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Keep line primitives visible when they share a depth plane with filled
|
|
96
|
+
* geometry. The same topology policy is consumed by the CPU and GPU-driven
|
|
97
|
+
* raster lanes so a mixed mesh does not change appearance when ownership
|
|
98
|
+
* moves between them.
|
|
99
|
+
*/
|
|
100
|
+
export function geometryRenderStateForTopology(
|
|
101
|
+
topology: PrimitiveTopology,
|
|
102
|
+
renderState: MaterialRenderState | undefined,
|
|
103
|
+
): MaterialRenderState | undefined {
|
|
104
|
+
if (topology !== 'line-list' && topology !== 'line-strip') return renderState;
|
|
105
|
+
return {
|
|
106
|
+
...renderState,
|
|
107
|
+
depthWriteEnabled: false,
|
|
108
|
+
depthCompare: 'less-equal',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* feat-20260604-learn-render-4.10-anti-aliasing-msaa M2 / w9: pick the static
|
|
114
|
+
* unlit geometry pipeline handle for a (tonemapActive x msaaActive)
|
|
115
|
+
* combination. The four mode axes (LDR/HDR x single/MSAA) map to the 14 static
|
|
116
|
+
* pipeline handles built in createRenderer (7 base + 7 count=4 variants). A
|
|
117
|
+
* pipeline's `multisample.count` must match the colour-attachment sampleCount,
|
|
118
|
+
* so the count=4 variant is required whenever the camera carries
|
|
119
|
+
* `antialias === 'msaa'`. Returns null when the requested pipeline was not
|
|
120
|
+
* built (empty-manifest path / MSAA variant build failure) -- the caller fires
|
|
121
|
+
* a structured `shader-compile-failed` on the null-narrow.
|
|
122
|
+
*/
|
|
123
|
+
// feat-20260615-pipeline-spec-ssot M6-T1: the standard-shading fallback
|
|
124
|
+
// selector was deleted. The pre-M6 selector silently substituted the
|
|
125
|
+
// boot-time URP `pipelineState.standardPipeline*` whenever the per-
|
|
126
|
+
// MaterialShader cache returned null and HDRP was inactive -- masking
|
|
127
|
+
// real PipelineSpecError build failures behind a layout-compatible-but-
|
|
128
|
+
// wrong PSO. Charter P3 explicit-failure now governs: a missing cache
|
|
129
|
+
// entry surfaces as null, and the per-submesh
|
|
130
|
+
// `if (smPipelineHandle === null) continue` skip-draw (which already
|
|
131
|
+
// covered the HDRP-active and skin-shader miss-skip paths) is the single
|
|
132
|
+
// uniform recovery shape across URP / HDRP / skin.
|
|
133
|
+
|
|
134
|
+
export function selectGeometryPipeline(
|
|
135
|
+
pipelineState: PipelineState,
|
|
136
|
+
tonemapActive: boolean,
|
|
137
|
+
msaaActive: boolean,
|
|
138
|
+
): RenderPipeline | null {
|
|
139
|
+
if (tonemapActive) {
|
|
140
|
+
return msaaActive ? pipelineState.unlitPipelineHdrMsaa : pipelineState.unlitPipelineHdr;
|
|
141
|
+
}
|
|
142
|
+
return msaaActive ? pipelineState.unlitPipelineMsaa : pipelineState.unlitPipeline;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* feat-city-glb Bug 5 (per-submesh transparency): true when EVERY submesh
|
|
147
|
+
* material of the entity is transparent (blend). Used by the geometry pass to
|
|
148
|
+
* decide whether to skip the whole entity (fully transparent → deferred to the
|
|
149
|
+
* blend sub-pass) vs. draw its opaque submeshes and skip only the transparent
|
|
150
|
+
* ones per-submesh.
|
|
151
|
+
*
|
|
152
|
+
* Falls back to the entity-level `material.transparent` when `materials` is
|
|
153
|
+
* absent (single-material entities / test fixtures), byte-identical to the
|
|
154
|
+
* pre-fix whole-entity gate.
|
|
155
|
+
*
|
|
156
|
+
* @internal
|
|
157
|
+
*/
|
|
158
|
+
export function isEntityFullyTransparent(source: {
|
|
159
|
+
readonly material: MaterialSnapshot;
|
|
160
|
+
readonly materials?: readonly MaterialSnapshot[];
|
|
161
|
+
}): boolean {
|
|
162
|
+
const mats = source.materials;
|
|
163
|
+
if (mats === undefined || mats.length === 0) return source.material.transparent === true;
|
|
164
|
+
for (let j = 0; j < mats.length; j++) {
|
|
165
|
+
if (mats[j]?.transparent !== true) return false;
|
|
166
|
+
}
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* feat-city-glb Bug 5: true when the entity has at least one transparent AND at
|
|
172
|
+
* least one opaque submesh — i.e. it must be drawn in BOTH the geometry pass
|
|
173
|
+
* (opaque submeshes) and the blend sub-pass (transparent submeshes). A pure-
|
|
174
|
+
* opaque or pure-transparent entity returns false (handled by the whole-entity
|
|
175
|
+
* fast paths).
|
|
176
|
+
*
|
|
177
|
+
* @internal
|
|
178
|
+
*/
|
|
179
|
+
export function entityHasTransparentSubmesh(source: {
|
|
180
|
+
readonly material: MaterialSnapshot;
|
|
181
|
+
readonly materials?: readonly MaterialSnapshot[];
|
|
182
|
+
}): boolean {
|
|
183
|
+
const mats = source.materials;
|
|
184
|
+
if (mats === undefined) return source.material.transparent === true;
|
|
185
|
+
for (let j = 0; j < mats.length; j++) {
|
|
186
|
+
if (mats[j]?.transparent === true) return true;
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* feat-20260601-device/gpu-residency-extraction M1 / D-9: resolve a texture's
|
|
193
|
+
* GPU view through the pull-model residency store. The three steps replace the
|
|
194
|
+
* pre-extraction single-call accessor on the registry:
|
|
195
|
+
* 1. fetch the TextureAsset POD off the registry (CPU; registry keeps PODs)
|
|
196
|
+
* 2. synchronously `ensureResident(handle, pod)` (first access builds the
|
|
197
|
+
* GPU texture + prewarmed mipmap blit; subsequent access is O(1))
|
|
198
|
+
* 3. return the GPU view (or undefined on POD miss / ensureResident err)
|
|
199
|
+
*
|
|
200
|
+
* Returns `undefined` when the POD is absent (handle never registered) or the
|
|
201
|
+
* upload fails (a structured error is fired). Callers then fall back to their
|
|
202
|
+
* existing placeholder view, preserving the pre-extraction fallback semantics.
|
|
203
|
+
*/
|
|
204
|
+
function isImageError(error: unknown): error is ImageError {
|
|
205
|
+
if (typeof error !== 'object' || error === null) return false;
|
|
206
|
+
const code = (error as { readonly code?: unknown }).code;
|
|
207
|
+
return typeof code === 'string' && code.startsWith('image-');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function residentTextureView(
|
|
211
|
+
world: World,
|
|
212
|
+
store: GpuResidencyCache,
|
|
213
|
+
runtime: RenderSystemRuntime,
|
|
214
|
+
handle: Handle<'TextureAsset', 'shared'>,
|
|
215
|
+
worldId: World | number = world,
|
|
216
|
+
): TextureView | undefined {
|
|
217
|
+
const podRes = resolveAssetHandle<TextureAsset>(world, handle);
|
|
218
|
+
if (!podRes.ok) return undefined;
|
|
219
|
+
const residentRes = store.ensureResident(handle, podRes.value, worldId);
|
|
220
|
+
if (!residentRes.ok) {
|
|
221
|
+
// Preserve the concrete asset-capability boundary on the renderer error
|
|
222
|
+
// channel. In particular, WebGL2 texture-dimension refusal must not
|
|
223
|
+
// collapse into the later debug-pink asset-not-registered fallback.
|
|
224
|
+
if (residentRes.error instanceof RhiError || isImageError(residentRes.error)) {
|
|
225
|
+
runtime.errorRegistry.fire(residentRes.error);
|
|
226
|
+
}
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
return store.getTextureGpuView(handle, worldId);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function residentSampler(
|
|
233
|
+
world: World,
|
|
234
|
+
store: GpuResidencyCache,
|
|
235
|
+
runtime: RenderSystemRuntime,
|
|
236
|
+
handle: Handle<'SamplerAsset', 'shared'>,
|
|
237
|
+
worldId: World | number = world,
|
|
238
|
+
): Sampler | undefined {
|
|
239
|
+
const podRes = resolveAssetHandle<SamplerAsset>(world, handle);
|
|
240
|
+
if (!podRes.ok) return undefined;
|
|
241
|
+
const residentRes = store.ensureSamplerResident(handle, podRes.value, worldId);
|
|
242
|
+
if (!residentRes.ok) {
|
|
243
|
+
runtime.errorRegistry.fire(residentRes.error);
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
return residentRes.value;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// feat-20260623-world-space-video-asset M4 / w16 (D-3): resolve the
|
|
250
|
+
// current-frame GPU view for a video-sourced texture field through the
|
|
251
|
+
// transient DynamicTextureStore, NOT the static `residentTextureView` /
|
|
252
|
+
// `ensureResident` cache (video never enters that switch; AC-08).
|
|
253
|
+
//
|
|
254
|
+
// Per frame: ask the host-registered VideoElementProvider (World Resource,
|
|
255
|
+
// D-1) for this entity's HTMLVideoElement, upload its current frame via
|
|
256
|
+
// `store.uploadFrame` (copyExternalImageToTexture), and return the resulting
|
|
257
|
+
// view. When the provider is absent / returns no element / the element has no
|
|
258
|
+
// decodable dimensions yet, fall back to a previously-uploaded view and
|
|
259
|
+
// finally to `undefined` (caller binds the default view this frame — charter
|
|
260
|
+
// P3 graceful, no garbage sampling). A failed GPU upload fires the structured
|
|
261
|
+
// RhiError on the engine channel and degrades to the default view.
|
|
262
|
+
//
|
|
263
|
+
// `highPerfAvailable` is the w17 capability probe; the high-perf
|
|
264
|
+
// GPUExternalTexture branch is a reserved hook (OOS-5) — when it ever becomes
|
|
265
|
+
// available the upload would route there. Today it is always false so the
|
|
266
|
+
// general copyExternalImageToTexture path is the only one taken.
|
|
267
|
+
type DynamicTextureStore = import('@forgeax/engine-assets-runtime').DynamicTextureStore;
|
|
268
|
+
|
|
269
|
+
type VideoUploadFailureEpisodes = Map<number, Set<number>>;
|
|
270
|
+
|
|
271
|
+
// The store is renderer-owned, so this keeps one failure episode per
|
|
272
|
+
// renderer/entity/clip without creating a second video system or leaking
|
|
273
|
+
// state across a replacement renderer.
|
|
274
|
+
const VIDEO_UPLOAD_FAILURE_EPISODES = new WeakMap<
|
|
275
|
+
DynamicTextureStore,
|
|
276
|
+
VideoUploadFailureEpisodes
|
|
277
|
+
>();
|
|
278
|
+
|
|
279
|
+
function markVideoUploadFailureEpisode(
|
|
280
|
+
store: DynamicTextureStore,
|
|
281
|
+
entityKey: number,
|
|
282
|
+
clip: Handle<'VideoAsset', 'shared'>,
|
|
283
|
+
): boolean {
|
|
284
|
+
let clips = VIDEO_UPLOAD_FAILURE_EPISODES.get(store);
|
|
285
|
+
if (clips === undefined) {
|
|
286
|
+
clips = new Map();
|
|
287
|
+
VIDEO_UPLOAD_FAILURE_EPISODES.set(store, clips);
|
|
288
|
+
}
|
|
289
|
+
let episodes = clips.get(entityKey);
|
|
290
|
+
if (episodes === undefined) {
|
|
291
|
+
episodes = new Set();
|
|
292
|
+
clips.set(entityKey, episodes);
|
|
293
|
+
}
|
|
294
|
+
const clipId = handleSlot(clip);
|
|
295
|
+
if (episodes.has(clipId)) return false;
|
|
296
|
+
episodes.add(clipId);
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function clearVideoUploadFailureEpisode(
|
|
301
|
+
store: DynamicTextureStore,
|
|
302
|
+
entityKey: number,
|
|
303
|
+
clip: Handle<'VideoAsset', 'shared'>,
|
|
304
|
+
): void {
|
|
305
|
+
const clips = VIDEO_UPLOAD_FAILURE_EPISODES.get(store);
|
|
306
|
+
const episodes = clips?.get(entityKey);
|
|
307
|
+
if (episodes === undefined) return;
|
|
308
|
+
episodes.delete(handleSlot(clip));
|
|
309
|
+
if (episodes.size === 0) clips?.delete(entityKey);
|
|
310
|
+
if (clips?.size === 0) VIDEO_UPLOAD_FAILURE_EPISODES.delete(store);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export function videoTextureView(
|
|
314
|
+
world: World,
|
|
315
|
+
store: DynamicTextureStore | undefined,
|
|
316
|
+
runtime: RenderSystemRuntime,
|
|
317
|
+
entityKey: number,
|
|
318
|
+
clip: Handle<'VideoAsset', 'shared'>,
|
|
319
|
+
highPerfAvailable: boolean,
|
|
320
|
+
): TextureView | undefined {
|
|
321
|
+
if (store === undefined) return undefined;
|
|
322
|
+
const provider = world.hasResource(VIDEO_ELEMENT_PROVIDER_KEY)
|
|
323
|
+
? world.getResource<VideoElementProvider>(VIDEO_ELEMENT_PROVIDER_KEY)
|
|
324
|
+
: undefined;
|
|
325
|
+
const element = provider?.getElement(entityKey as EntityHandle, clip);
|
|
326
|
+
// AC-10 double-miss: a VideoPlayer entity can reach NEITHER upload path this
|
|
327
|
+
// frame — no host HTMLVideoElement (general copyExternalImageToTexture path)
|
|
328
|
+
// AND no high-perf GPUExternalTexture path. This is the genuine "this backend
|
|
329
|
+
// exposes no usable video upload path" case (no provider registered, or the
|
|
330
|
+
// provider yields nothing while the high-perf reserved hook is unavailable —
|
|
331
|
+
// OOS-5 keeps it always false today). Rather than silently binding the
|
|
332
|
+
// default view, fire the structured VideoUploadUnsupportedError on the engine
|
|
333
|
+
// error channel so an AI user can detect the dead path via `.code` / `.hint`
|
|
334
|
+
// (charter P3; AC-10 signal lives on the REAL per-frame upload path, not an
|
|
335
|
+
// orphan system). The default view is still bound this frame so the draw
|
|
336
|
+
// does not crash (graceful degradation), but the failure is no longer silent.
|
|
337
|
+
if (element === undefined && !highPerfAvailable) {
|
|
338
|
+
if (markVideoUploadFailureEpisode(store, entityKey, clip)) {
|
|
339
|
+
runtime.errorRegistry.fire(new VideoUploadUnsupportedError());
|
|
340
|
+
}
|
|
341
|
+
return store.getView(clip);
|
|
342
|
+
}
|
|
343
|
+
// D-2 / w17 high-perf reserved hook: a future GPUExternalTexture import path
|
|
344
|
+
// would key off `highPerfAvailable` here. It is always false today
|
|
345
|
+
// (importExternalTexture absent), so the general copyExternalImageToTexture
|
|
346
|
+
// path below is the sole route end-to-end.
|
|
347
|
+
if (element === undefined) {
|
|
348
|
+
clearVideoUploadFailureEpisode(store, entityKey, clip);
|
|
349
|
+
return store.getView(clip);
|
|
350
|
+
}
|
|
351
|
+
const width = element.videoWidth;
|
|
352
|
+
const height = element.videoHeight;
|
|
353
|
+
// Metadata dimensions can be non-zero before the decoder has produced a
|
|
354
|
+
// current frame. WebGPU rejects copyExternalImageToTexture in that window
|
|
355
|
+
// because the video element has no back resource yet; keep the previous
|
|
356
|
+
// frame/default view until HAVE_CURRENT_DATA (2) is reached.
|
|
357
|
+
if (width <= 0 || height <= 0 || element.readyState < 2) return store.getView(clip);
|
|
358
|
+
const uploaded = store.uploadFrame(clip, element, width, height);
|
|
359
|
+
if (uploaded === undefined) return store.getView(clip);
|
|
360
|
+
if (!uploaded.ok) {
|
|
361
|
+
runtime.errorRegistry.fire(uploaded.error);
|
|
362
|
+
return store.getView(clip);
|
|
363
|
+
}
|
|
364
|
+
clearVideoUploadFailureEpisode(store, entityKey, clip);
|
|
365
|
+
return uploaded.value;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// feat-20260621-learn-render-5-5-parallax M2 / w8 (D-3): the built-in
|
|
369
|
+
// standard-PBR user-region texture field order, used when the shader is not
|
|
370
|
+
// resolvable through getParamSchema (cross-worktree late-register). Mirrors
|
|
371
|
+
// derive(default-standard-pbr).textureFieldNames.
|
|
372
|
+
export const BUILTIN_USER_REGION_TEXTURE_FIELDS: readonly string[] = [
|
|
373
|
+
'baseColorTexture',
|
|
374
|
+
'metallicRoughnessTexture',
|
|
375
|
+
'normalTexture',
|
|
376
|
+
'specularTintTexture',
|
|
377
|
+
'emissiveTexture',
|
|
378
|
+
'occlusionTexture',
|
|
379
|
+
];
|
|
380
|
+
|
|
381
|
+
const LEGACY_MATERIAL_TEXTURE_SCALE_OFFSET = 80;
|
|
382
|
+
const STANDARD_PBR_TEXTURE_SCALE_OFFSET = 96;
|
|
383
|
+
const MATERIAL_TEXTURE_SCALE_FIELDS = [
|
|
384
|
+
'baseColorTexture',
|
|
385
|
+
'metallicRoughnessTexture',
|
|
386
|
+
'normalTexture',
|
|
387
|
+
'specularTintTexture',
|
|
388
|
+
'emissiveTexture',
|
|
389
|
+
'occlusionTexture',
|
|
390
|
+
] as const;
|
|
391
|
+
const LEGACY_MATERIAL_TEXTURE_SCALE_FIELDS = [
|
|
392
|
+
'baseColorTexture',
|
|
393
|
+
'metallicRoughnessTexture',
|
|
394
|
+
'normalTexture',
|
|
395
|
+
'emissiveTexture',
|
|
396
|
+
'occlusionTexture',
|
|
397
|
+
] as const;
|
|
398
|
+
const STANDARD_PBR_TEXTURE_COORDINATE_OFFSET = 96;
|
|
399
|
+
const STANDARD_PBR_TEXTURE_COORDINATE_STRIDE = 8;
|
|
400
|
+
const DEFAULT_LEGACY_TEXTURE_SCALES = new Float32Array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
|
|
401
|
+
const DEFAULT_STANDARD_TEXTURE_COORDINATES = new Float32Array([
|
|
402
|
+
0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0,
|
|
403
|
+
0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
|
|
404
|
+
]);
|
|
405
|
+
|
|
406
|
+
/** Derives the logical-content UV scale for an uploaded material texture. */
|
|
407
|
+
export function materialTextureUvScale(
|
|
408
|
+
texture: Pick<TextureAsset, 'width' | 'height' | 'format'> | undefined,
|
|
409
|
+
): readonly [number, number] {
|
|
410
|
+
if (texture === undefined) return [1, 1];
|
|
411
|
+
return deriveTextureExtent(texture.format, texture.width, texture.height).uvScale;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function materialTextureForField(
|
|
415
|
+
material: MaterialSnapshot,
|
|
416
|
+
field: string,
|
|
417
|
+
): Handle<'TextureAsset', 'shared'> | undefined {
|
|
418
|
+
if (field === 'emissiveTexture') return material.emissiveTexture;
|
|
419
|
+
if (field === 'occlusionTexture') return material.occlusionTexture;
|
|
420
|
+
return material.textureHandles?.get(field);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Appends the engine-owned scale for every built-in material texture binding.
|
|
425
|
+
* Asset dimensions remain logical; this is the sole record-stage projection
|
|
426
|
+
* from a bound texture asset to its shader sampling coordinates.
|
|
427
|
+
*/
|
|
428
|
+
type MaterialUboPayload = ArrayBuffer | Uint8Array | Float32Array;
|
|
429
|
+
|
|
430
|
+
function materialUboFloatView(payload: MaterialUboPayload): Float32Array {
|
|
431
|
+
if (payload instanceof Float32Array) return payload;
|
|
432
|
+
return payload instanceof Uint8Array
|
|
433
|
+
? new Float32Array(payload.buffer, payload.byteOffset, payload.byteLength / 4)
|
|
434
|
+
: new Float32Array(payload);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
export function applyMaterialTextureUvScales(
|
|
438
|
+
payload: MaterialUboPayload,
|
|
439
|
+
material: MaterialSnapshot,
|
|
440
|
+
world: World,
|
|
441
|
+
): void {
|
|
442
|
+
const f32 = materialUboFloatView(payload);
|
|
443
|
+
const coordinateSchema = materialCoordinateSchema(material);
|
|
444
|
+
if (coordinateSchema !== undefined) {
|
|
445
|
+
const coordinateRecords = derivedParamSchema(coordinateSchema).coordinateRecords;
|
|
446
|
+
for (const record of coordinateRecords) {
|
|
447
|
+
const field = record.parameter;
|
|
448
|
+
const handle = materialTextureForField(material, field);
|
|
449
|
+
const resolvedTexture =
|
|
450
|
+
handle === undefined ? undefined : resolveAssetHandle<TextureAsset>(world, handle);
|
|
451
|
+
const texture = resolvedTexture?.ok === true ? resolvedTexture.value : undefined;
|
|
452
|
+
const [u, v] = materialTextureUvScale(texture);
|
|
453
|
+
const coordinates = resolveMaterialTextureCoordinates(
|
|
454
|
+
material.textureCoordinates?.get(field),
|
|
455
|
+
);
|
|
456
|
+
const offset = record.offset / 4;
|
|
457
|
+
f32[offset] = coordinates.transform.offset[0];
|
|
458
|
+
f32[offset + 1] = coordinates.transform.offset[1];
|
|
459
|
+
f32[offset + 2] = coordinates.transform.scale[0];
|
|
460
|
+
f32[offset + 3] = coordinates.transform.scale[1];
|
|
461
|
+
f32[offset + 4] = coordinates.set;
|
|
462
|
+
f32[offset + 5] = coordinates.transform.rotation;
|
|
463
|
+
f32[offset + 6] = u;
|
|
464
|
+
f32[offset + 7] = v;
|
|
465
|
+
}
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
// Standard PBR grew two authored coat fields before the engine-owned UV
|
|
469
|
+
// tail. Sprite, sprite-lit, unlit, and text keep their own 80-byte tail
|
|
470
|
+
// position because their WGSL layouts do not carry clearcoat.
|
|
471
|
+
const textureScaleOffset = isStandardPbrMaterialShader(material.materialShaderId)
|
|
472
|
+
? STANDARD_PBR_TEXTURE_SCALE_OFFSET
|
|
473
|
+
: LEGACY_MATERIAL_TEXTURE_SCALE_OFFSET;
|
|
474
|
+
const isStandardPbr = textureScaleOffset === STANDARD_PBR_TEXTURE_SCALE_OFFSET;
|
|
475
|
+
const hasTextureMetadata =
|
|
476
|
+
material.textureCoordinates !== undefined ||
|
|
477
|
+
material.textureHandles !== undefined ||
|
|
478
|
+
material.videoTextureFields !== undefined ||
|
|
479
|
+
material.baseColorTexture !== undefined ||
|
|
480
|
+
material.metallicRoughnessTexture !== undefined ||
|
|
481
|
+
material.normalTexture !== undefined ||
|
|
482
|
+
material.emissiveTexture !== undefined ||
|
|
483
|
+
material.occlusionTexture !== undefined;
|
|
484
|
+
if (!hasTextureMetadata) {
|
|
485
|
+
f32.set(
|
|
486
|
+
isStandardPbr ? DEFAULT_STANDARD_TEXTURE_COORDINATES : DEFAULT_LEGACY_TEXTURE_SCALES,
|
|
487
|
+
textureScaleOffset / 4,
|
|
488
|
+
);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const fields = isStandardPbr
|
|
492
|
+
? MATERIAL_TEXTURE_SCALE_FIELDS
|
|
493
|
+
: LEGACY_MATERIAL_TEXTURE_SCALE_FIELDS;
|
|
494
|
+
for (let index = 0; index < fields.length; index++) {
|
|
495
|
+
const field = fields[index];
|
|
496
|
+
if (field === undefined) continue;
|
|
497
|
+
const handle = materialTextureForField(material, field);
|
|
498
|
+
const resolved =
|
|
499
|
+
handle === undefined ? undefined : resolveAssetHandle<TextureAsset>(world, handle);
|
|
500
|
+
const texture = resolved?.ok === true ? resolved.value : undefined;
|
|
501
|
+
const [u, v] = materialTextureUvScale(texture);
|
|
502
|
+
if (isStandardPbr) {
|
|
503
|
+
const coordinates = material.textureCoordinates?.get(field);
|
|
504
|
+
const transform = coordinates?.transform;
|
|
505
|
+
const offset =
|
|
506
|
+
STANDARD_PBR_TEXTURE_COORDINATE_OFFSET / 4 + index * STANDARD_PBR_TEXTURE_COORDINATE_STRIDE;
|
|
507
|
+
f32[offset] = transform?.offset?.[0] ?? 0;
|
|
508
|
+
f32[offset + 1] = transform?.offset?.[1] ?? 0;
|
|
509
|
+
f32[offset + 2] = transform?.scale?.[0] ?? 1;
|
|
510
|
+
f32[offset + 3] = transform?.scale?.[1] ?? 1;
|
|
511
|
+
f32[offset + 4] = coordinates?.set ?? 0;
|
|
512
|
+
f32[offset + 5] = transform?.rotation ?? 0;
|
|
513
|
+
f32[offset + 6] = u;
|
|
514
|
+
f32[offset + 7] = v;
|
|
515
|
+
} else {
|
|
516
|
+
const offset = textureScaleOffset / 4 + index * 2;
|
|
517
|
+
f32[offset] = u;
|
|
518
|
+
f32[offset + 1] = v;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function materialCoordinateSchema(
|
|
524
|
+
material: MaterialSnapshot,
|
|
525
|
+
): readonly ParamSchemaEntry[] | undefined {
|
|
526
|
+
if (material.materialParamSchema !== undefined && material.materialParamSchema.length > 0) {
|
|
527
|
+
return material.materialParamSchema;
|
|
528
|
+
}
|
|
529
|
+
switch (material.materialShaderId) {
|
|
530
|
+
case 'forgeax::default-unlit':
|
|
531
|
+
return DEFAULT_UNLIT_PARAM_SCHEMA;
|
|
532
|
+
case 'forgeax::sprite':
|
|
533
|
+
case 'forgeax::sprite-lit':
|
|
534
|
+
return DEFAULT_SPRITE_PARAM_SCHEMA;
|
|
535
|
+
case 'forgeax::msdf-text':
|
|
536
|
+
return DEFAULT_MSDF_TEXT_PARAM_SCHEMA;
|
|
537
|
+
default:
|
|
538
|
+
return undefined;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* feat-20260621-learn-render-5-5-parallax M2 / w8 (D-3): ordered user-region
|
|
544
|
+
* texture field names for a material's bind-group assembly, derived from the
|
|
545
|
+
* shader's paramSchema via the `derive()` SSOT (insertion order = sampler/
|
|
546
|
+
* texture pair order in derive().bglEntries). Falls back to the built-in 4
|
|
547
|
+
* fields when the schema is unavailable.
|
|
548
|
+
*/
|
|
549
|
+
export function userRegionTextureFieldOrder(
|
|
550
|
+
schema: Parameters<typeof derive>[0] | undefined,
|
|
551
|
+
): readonly string[] {
|
|
552
|
+
if (schema === undefined || schema.length === 0) return BUILTIN_USER_REGION_TEXTURE_FIELDS;
|
|
553
|
+
const fields = [...derivedParamSchema(schema).textureFieldNames];
|
|
554
|
+
return fields.length === 0 ? BUILTIN_USER_REGION_TEXTURE_FIELDS : fields;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* feat-20260621-learn-render-5-5-parallax M2 / w8: the fallback texture view
|
|
559
|
+
* for a user-region field when no handle is provided (graceful, charter P3).
|
|
560
|
+
* normalTexture decodes to a flat tangent normal; everything else (baseColor,
|
|
561
|
+
* MR, height, ...) uses the 1x1 white default (height white -> zero displacement).
|
|
562
|
+
*/
|
|
563
|
+
export function defaultViewForUserRegionField(
|
|
564
|
+
field: string,
|
|
565
|
+
pipelineState: PipelineState,
|
|
566
|
+
): TextureView {
|
|
567
|
+
if (field === 'normalTexture') return pipelineState.defaultNormalTextureView;
|
|
568
|
+
if (field === 'baseColorTexture') return pipelineState.fallbackTextureView;
|
|
569
|
+
return pipelineState.defaultWhiteTextureView;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* feat-20260527-sprite-nineslice M4 / w17 (AC-16): once-per-renderable
|
|
574
|
+
* detection of "Transform.scale below the four 9-slice corner anchors". Pure
|
|
575
|
+
* helper extracted out of recordFrame so unit tests can drive it without a
|
|
576
|
+
* GPU device — the recordFrame loop calls this with its `transformWorld` /
|
|
577
|
+
* `slices` / `renderableIndex` / `seenIndices` / `metrics` arguments.
|
|
578
|
+
*
|
|
579
|
+
* The scale-vs-anchor formula mirrors plan-strategy §D-3 — the world x scale must
|
|
580
|
+
* accommodate `|slices.x| + |slices.z|`, and `scaleY` must accommodate
|
|
581
|
+
* `|slices.y| + |slices.w|`. Slices ≡ all zero is a no-op (legacy quad
|
|
582
|
+
* path); a breach increments `nineslice.scale-too-small` exactly once per
|
|
583
|
+
* `renderableIndex` per RenderSystem lifetime via the `seenIndices` Set
|
|
584
|
+
* (the same warn-once anchor pattern used for missing-texture sprites).
|
|
585
|
+
*
|
|
586
|
+
* @param transformWorld The entity's resolved Transform.world mat4 (16 floats column-major).
|
|
587
|
+
* @param slices The four anchor distances `[left, top, right, bottom]`
|
|
588
|
+
* (sentinel `bottom < 0` for tile mode is consumed via abs()).
|
|
589
|
+
* @param renderableIndex The entity index into the validated renderables list.
|
|
590
|
+
* @param seenIndices The per-frame-state guard Set; entries are added on increment.
|
|
591
|
+
* @param metrics The owner-provided EngineMetrics counter.
|
|
592
|
+
* @internal — exported for unit-test access (w17).
|
|
593
|
+
*/
|
|
594
|
+
export function detectNineSliceScaleTooSmall(
|
|
595
|
+
transformWorld: Float32Array,
|
|
596
|
+
slices: readonly [number, number, number, number],
|
|
597
|
+
renderableIndex: number,
|
|
598
|
+
seenIndices: Set<number>,
|
|
599
|
+
metrics: { increment(name: string): void },
|
|
600
|
+
): void {
|
|
601
|
+
const anyNonZero = slices[0] !== 0 || slices[1] !== 0 || slices[2] !== 0 || slices[3] !== 0;
|
|
602
|
+
if (!anyNonZero) return;
|
|
603
|
+
const sx = Math.hypot(transformWorld[0] ?? 1, transformWorld[1] ?? 0, transformWorld[2] ?? 0);
|
|
604
|
+
const sy = Math.hypot(transformWorld[4] ?? 0, transformWorld[5] ?? 1, transformWorld[6] ?? 0);
|
|
605
|
+
const horizontalAnchor = Math.abs(slices[0]) + Math.abs(slices[2]);
|
|
606
|
+
const verticalAnchor = Math.abs(slices[1]) + Math.abs(slices[3]);
|
|
607
|
+
if (sx < horizontalAnchor || sy < verticalAnchor) {
|
|
608
|
+
if (!seenIndices.has(renderableIndex)) {
|
|
609
|
+
seenIndices.add(renderableIndex);
|
|
610
|
+
metrics.increment('nineslice.scale-too-small');
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Build the 128-byte Material UBO payload for a PBR / unlit material entry
|
|
617
|
+
* (feat-20260527-sprite-nineslice M2 / w11; D-7 regression-net helper).
|
|
618
|
+
*
|
|
619
|
+
* Byte-for-byte equivalent to the legacy hard-coded PBR write path; each
|
|
620
|
+
* deviation is caught by `render-system-record-pbr-ubo-stable.test.ts`.
|
|
621
|
+
* The schema-driven paramSnapshot overlay (feat-20260523 M9-T05; AC-14)
|
|
622
|
+
* positions vec4 / f32 slots onto std140 [slot0 vec4, slot1 f32 metallic,
|
|
623
|
+
* slot1 f32 roughness] mirroring the engine-shipped default-standard-pbr
|
|
624
|
+
* Material struct.
|
|
625
|
+
*/
|
|
626
|
+
export function buildPbrMaterialUboPayload(material: MaterialSnapshot): Uint8Array {
|
|
627
|
+
const buf = new Uint8Array(STANDARD_PBR_UBO_SIZE);
|
|
628
|
+
writePbrMaterialUboPayload(buf, material);
|
|
629
|
+
return buf;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Write the standard material payload into caller-owned storage.
|
|
634
|
+
*
|
|
635
|
+
* The allocating wrapper above remains the byte-stable test/helper surface,
|
|
636
|
+
* while the frame recorder reuses one scratch slot for all materials. A
|
|
637
|
+
* scene with thousands of submeshes otherwise allocates one 304-byte
|
|
638
|
+
* Uint8Array per material per frame, creating avoidable GC pressure without
|
|
639
|
+
* changing GPU-visible bytes.
|
|
640
|
+
*/
|
|
641
|
+
export function writePbrMaterialUboPayload(
|
|
642
|
+
buf: Uint8Array | Float32Array,
|
|
643
|
+
material: MaterialSnapshot,
|
|
644
|
+
): void {
|
|
645
|
+
if (buf.byteLength < STANDARD_PBR_UBO_SIZE) {
|
|
646
|
+
throw new RangeError(
|
|
647
|
+
`writePbrMaterialUboPayload: expected at least ${STANDARD_PBR_UBO_SIZE} bytes, got ${buf.byteLength}`,
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
buf.fill(0);
|
|
651
|
+
const f32 = materialUboFloatView(buf);
|
|
652
|
+
// Layout (issue-1: channelMap split per D-8) -- byte-equivalent to the
|
|
653
|
+
// post-split sidecar paramSchema for default-standard-pbr (12 numeric
|
|
654
|
+
// entries packed std140 into one merged UBO at binding(0)).
|
|
655
|
+
// f32[0..3] baseColor (offset 0, vec4)
|
|
656
|
+
// f32[4] metallic (offset 16)
|
|
657
|
+
// f32[5] roughness (offset 20)
|
|
658
|
+
// f32[6] metallicChannel (offset 24) -- glTF 2.0 default = B = 2
|
|
659
|
+
// f32[7] roughnessChannel (offset 28) -- glTF 2.0 default = G = 1
|
|
660
|
+
// f32[8] aoChannel (offset 32) -- glTF 2.0 default = R = 0
|
|
661
|
+
// f32[9] extraChannel (offset 36) -- reserved = 0
|
|
662
|
+
// (offset 40..47 implicit pad: vec3 align=16)
|
|
663
|
+
// f32[12..14] emissive (offset 48, vec3)
|
|
664
|
+
// f32[15] emissiveIntensity (offset 60)
|
|
665
|
+
// f32[16] occlusionStrength (offset 64)
|
|
666
|
+
// f32[17] alphaCutoff (offset 68)
|
|
667
|
+
// f32[18] clearcoat (offset 72)
|
|
668
|
+
// f32[19] clearcoatRoughness (offset 76)
|
|
669
|
+
// f32[20..22] specularTint (offset 80, vec3)
|
|
670
|
+
// (offset 92..95 alignment pad)
|
|
671
|
+
// f32[24..71] engine-owned texture coordinate records (offset 96)
|
|
672
|
+
// f32[72] normalScale (offset 288)
|
|
673
|
+
f32[0] = material.baseColor[0] ?? 0;
|
|
674
|
+
f32[1] = material.baseColor[1] ?? 0;
|
|
675
|
+
f32[2] = material.baseColor[2] ?? 0;
|
|
676
|
+
f32[3] = 1;
|
|
677
|
+
f32[4] = material.metallic;
|
|
678
|
+
f32[5] = material.roughness;
|
|
679
|
+
// channelMap default = (B, G, R, _) per AGENTS.md + glTF 2.0
|
|
680
|
+
// KHR_materials_pbrSpecularGlossiness ARM packing -- now 4 independent
|
|
681
|
+
// f32 selectors; fragment casts each to u32 at the pick site.
|
|
682
|
+
f32[6] = 2; // metallicChannel <- B
|
|
683
|
+
f32[7] = 1; // roughnessChannel <- G
|
|
684
|
+
f32[8] = 0; // aoChannel <- R
|
|
685
|
+
f32[9] = 0; // extraChannel <- reserved
|
|
686
|
+
// emissive vec3 + emissiveIntensity (offset 48..63)
|
|
687
|
+
const em = material.emissive;
|
|
688
|
+
f32[12] = em?.[0] ?? 0;
|
|
689
|
+
f32[13] = em?.[1] ?? 0;
|
|
690
|
+
f32[14] = em?.[2] ?? 0;
|
|
691
|
+
f32[15] = material.emissiveIntensity ?? 0;
|
|
692
|
+
// occlusionStrength (offset 64)
|
|
693
|
+
f32[16] = material.occlusionStrength ?? 1;
|
|
694
|
+
// alphaCutoff (offset 68).
|
|
695
|
+
const alphaCutoff = material.paramSnapshot?.alphaCutoff;
|
|
696
|
+
f32[17] = typeof alphaCutoff === 'number' ? alphaCutoff : 0;
|
|
697
|
+
f32[18] = material.clearcoat ?? 0;
|
|
698
|
+
f32[19] = material.clearcoatRoughness ?? 0.5;
|
|
699
|
+
const specularTint = material.specularTint;
|
|
700
|
+
f32[20] = specularTint?.[0] ?? 1;
|
|
701
|
+
f32[21] = specularTint?.[1] ?? 1;
|
|
702
|
+
f32[22] = specularTint?.[2] ?? 1;
|
|
703
|
+
f32[72] = material.normalScale ?? 1;
|
|
704
|
+
// Schema-driven paramSnapshot overlay (feat-20260523 M9-T05, AC-14):
|
|
705
|
+
// for user-shaders with a paramSnapshot, project the first vec4/color
|
|
706
|
+
// entry onto slot 0 and the first two f32 entries onto slot 1's first
|
|
707
|
+
// two floats. The default-standard-pbr path lands on the same offsets
|
|
708
|
+
// via the explicit fields above, so the overlay is a no-op for the
|
|
709
|
+
// engine's stock PBR shader (charter P4 + R-H regression fence).
|
|
710
|
+
const paramSnap = material.paramSnapshot;
|
|
711
|
+
if (paramSnap !== undefined) {
|
|
712
|
+
const f32Snap = (name: string): number | undefined => {
|
|
713
|
+
const v = paramSnap[name];
|
|
714
|
+
return typeof v === 'number' ? v : undefined;
|
|
715
|
+
};
|
|
716
|
+
const colorSnap = (name: string): readonly number[] | undefined => {
|
|
717
|
+
const v = paramSnap[name];
|
|
718
|
+
return Array.isArray(v) && v.every((x) => typeof x === 'number')
|
|
719
|
+
? (v as readonly number[])
|
|
720
|
+
: undefined;
|
|
721
|
+
};
|
|
722
|
+
// Walk schema in declared order, fill positional UBO slots.
|
|
723
|
+
const materialShaderId = material.materialShaderId;
|
|
724
|
+
// Note: schema lookup is the caller's job (it owns the runtime ref);
|
|
725
|
+
// when the helper has no access to runtime, paramSnap is consumed
|
|
726
|
+
// positionally without a schema walk. The inline caller (recordFrame)
|
|
727
|
+
// still performs the schema-driven walk and writes the overlay before
|
|
728
|
+
// queueing this payload, so this helper is only the byte-stable
|
|
729
|
+
// baseline. To preserve byte-for-byte equivalence in the helper-only
|
|
730
|
+
// unit-test path, the overlay pass is skipped when the helper is
|
|
731
|
+
// called without an external schema reference.
|
|
732
|
+
void materialShaderId;
|
|
733
|
+
void f32Snap;
|
|
734
|
+
void colorSnap;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Generic std140 UBO writer driven by `derive(paramSchema).uboLayout.entries`
|
|
740
|
+
* (feat-20260625-refactor-sprite-as-transparent-mesh M1 / w3, plan-strategy
|
|
741
|
+
* section 2 D-2).
|
|
742
|
+
*
|
|
743
|
+
* For each numeric entry in the schema, looks up the matching value in
|
|
744
|
+
* `paramSnapshot` and writes it at the std140 offset `derive` computed.
|
|
745
|
+
* Vec / color entries pull from `paramSnapshot[name]` as a `readonly number[]`
|
|
746
|
+
* (writes `min(size/4, value.length)` floats, padding with 0 if shorter for
|
|
747
|
+
* the field's declared width); scalar entries pull a single number.
|
|
748
|
+
*
|
|
749
|
+
* Behaviour:
|
|
750
|
+
* - schema or snapshot `undefined` -> no writes (caller may keep payload
|
|
751
|
+
* baseline).
|
|
752
|
+
* - missing snapshot field -> that field's bytes are left untouched
|
|
753
|
+
* (overlay semantics; same shape the legacy inline overlay had).
|
|
754
|
+
* - field type the writer cannot interpret (texture / sampler / storage_
|
|
755
|
+
* buffer / value-type mismatch) -> skipped silently; `derive` strips
|
|
756
|
+
* non-numeric entries from `uboLayout.entries` so the loop only iterates
|
|
757
|
+
* numeric fields.
|
|
758
|
+
*
|
|
759
|
+
* The writer reads `paramSnapshot` only -- it does NOT call
|
|
760
|
+
* `runtime.assets.get<MaterialAsset>` or cast `firstMaterial`. Gate R-H
|
|
761
|
+
* (plan-strategy section 5.6) bans those paths through
|
|
762
|
+
* `scripts/forgeax/check-render-record-no-material-asset-get.mjs`.
|
|
763
|
+
*
|
|
764
|
+
* standard-pbr remains byte-identical to `buildPbrMaterialUboPayload`: the
|
|
765
|
+
* engine's stock PBR material ships `paramSnapshot: undefined`, so this
|
|
766
|
+
* writer is a no-op on that path; the explicit field writes in the helper
|
|
767
|
+
* above cover every byte. User shaders (sprite-shaped 4 x vec4 or another
|
|
768
|
+
* paramSchema) get their fields written at the offsets declared by derive.
|
|
769
|
+
*
|
|
770
|
+
* @internal export-for-test (consumed inside `recordFrame` + render-system-
|
|
771
|
+
* record.test.ts; not part of the package's public surface).
|
|
772
|
+
*/
|
|
773
|
+
export function applyParamSnapshotToUbo(
|
|
774
|
+
payload: MaterialUboPayload,
|
|
775
|
+
paramSchema: readonly ParamSchemaEntry[] | undefined,
|
|
776
|
+
paramSnapshot:
|
|
777
|
+
| Readonly<Record<string, number | readonly number[] | string | undefined>>
|
|
778
|
+
| undefined,
|
|
779
|
+
): void {
|
|
780
|
+
if (paramSchema === undefined) return;
|
|
781
|
+
if (paramSnapshot === undefined) return;
|
|
782
|
+
const f32 = materialUboFloatView(payload);
|
|
783
|
+
const { uboLayout } = derivedParamSchema(paramSchema);
|
|
784
|
+
for (const entry of uboLayout.entries) {
|
|
785
|
+
const value = paramSnapshot[entry.name];
|
|
786
|
+
if (value === undefined) continue;
|
|
787
|
+
const f32Offset = entry.offset / 4;
|
|
788
|
+
const f32Width = entry.size / 4;
|
|
789
|
+
if (typeof value === 'number') {
|
|
790
|
+
// Scalar f32 / i32 / u32 -- single-slot write. (i32 / u32 still arrive
|
|
791
|
+
// as a JS number; the GPU side reads the four bytes as the declared
|
|
792
|
+
// type, so an f32 write is the correct bit pattern when the caller
|
|
793
|
+
// already produced an integer value.)
|
|
794
|
+
if (f32Width >= 1) f32[f32Offset] = value;
|
|
795
|
+
continue;
|
|
796
|
+
}
|
|
797
|
+
if (Array.isArray(value)) {
|
|
798
|
+
const arr = value as readonly number[];
|
|
799
|
+
const writeCount = Math.min(arr.length, f32Width);
|
|
800
|
+
for (let i = 0; i < writeCount; i++) {
|
|
801
|
+
const v = arr[i];
|
|
802
|
+
if (typeof v === 'number') f32[f32Offset + i] = v;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
// string values (texture GUIDs) belong to texture bindings, not the
|
|
806
|
+
// UBO; derive's uboLayout.entries already strips non-numeric schema
|
|
807
|
+
// entries, so we will not see a uboLayout entry whose snapshot value
|
|
808
|
+
// is a string under normal flow. Skip defensively if we do.
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* feat-20260704 M3/w19: shared per-submesh material bind-group assembly, hoisted
|
|
814
|
+
* from the `buildPerSubmeshMaterialBg` closure inside recordMainPass so both the
|
|
815
|
+
* geometry pass and the LDR blend sub-pass (extracted to separate functions)
|
|
816
|
+
* call the identical layout.
|
|
817
|
+
*
|
|
818
|
+
* feat-city-glb Bug 5 (per-submesh transparency): a transparent PBR submesh
|
|
819
|
+
* binds the identical metallic/roughness/normal/emissive/occlusion +
|
|
820
|
+
* Skylight layout the geometry pass uses (the sub-pass previously bound a
|
|
821
|
+
* sprite-only BG, which cannot render a PBR decal). The per-frame closure state
|
|
822
|
+
* (runtime / pipelineState / world / store / skylightResources / the shared
|
|
823
|
+
* material BG cache + counters) is threaded through `deps`; the caller passes
|
|
824
|
+
* the per-submesh material snapshot + entityKey (video texture routing) and sets
|
|
825
|
+
* the dynamic UBO offset itself.
|
|
826
|
+
*
|
|
827
|
+
* @internal
|
|
828
|
+
*/
|
|
829
|
+
export interface PerSubmeshMaterialBgDeps {
|
|
830
|
+
readonly runtime: RenderSystemRuntime;
|
|
831
|
+
readonly pipelineState: PipelineState;
|
|
832
|
+
readonly world: World;
|
|
833
|
+
readonly store: GpuResidencyCache;
|
|
834
|
+
readonly materialSlice: number;
|
|
835
|
+
readonly videoHighPerfAvailable: boolean;
|
|
836
|
+
readonly skylightResources: SkylightBindGroupResources;
|
|
837
|
+
readonly materialBgShared: Map<string, WeakMap<object, unknown>>;
|
|
838
|
+
/** Cross-frame final BG reuse keyed by the stable source material handle. */
|
|
839
|
+
readonly materialBgAssemblyCache: Map<string, MaterialBgAssemblyCacheEntry>;
|
|
840
|
+
readonly bindGroupCounts: BindGroupCounts;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/** @internal Exported only so buffer-generation invalidation stays regression-tested. */
|
|
844
|
+
export function isMaterialBgAssemblyCacheHit(
|
|
845
|
+
cached: MaterialBgAssemblyCacheEntry | undefined,
|
|
846
|
+
material: MaterialSnapshot,
|
|
847
|
+
materialBgl: BindGroupLayout,
|
|
848
|
+
materialBuffer: Buffer,
|
|
849
|
+
skylightResources: SkylightBindGroupResources,
|
|
850
|
+
materialResourceEpoch: number,
|
|
851
|
+
): cached is MaterialBgAssemblyCacheEntry {
|
|
852
|
+
return (
|
|
853
|
+
cached?.material === material &&
|
|
854
|
+
cached.materialResourceEpoch === materialResourceEpoch &&
|
|
855
|
+
cached.materialBgl === materialBgl &&
|
|
856
|
+
cached.materialBuffer === materialBuffer &&
|
|
857
|
+
cached.skylightResources.irradianceView === skylightResources.irradianceView &&
|
|
858
|
+
cached.skylightResources.irradianceSampler === skylightResources.irradianceSampler &&
|
|
859
|
+
cached.skylightResources.prefilterView === skylightResources.prefilterView &&
|
|
860
|
+
cached.skylightResources.prefilterSampler === skylightResources.prefilterSampler &&
|
|
861
|
+
cached.skylightResources.brdfLutView === skylightResources.brdfLutView &&
|
|
862
|
+
cached.skylightResources.brdfLutSampler === skylightResources.brdfLutSampler &&
|
|
863
|
+
cached.skylightResources.intensityBuffer === skylightResources.intensityBuffer
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
export function buildPerSubmeshMaterialBg(
|
|
868
|
+
deps: PerSubmeshMaterialBgDeps,
|
|
869
|
+
submeshMaterial: MaterialSnapshot,
|
|
870
|
+
entityKey: number,
|
|
871
|
+
materialWorld: World = deps.world,
|
|
872
|
+
): BindGroup {
|
|
873
|
+
const {
|
|
874
|
+
runtime,
|
|
875
|
+
pipelineState,
|
|
876
|
+
store,
|
|
877
|
+
materialSlice,
|
|
878
|
+
videoHighPerfAvailable,
|
|
879
|
+
skylightResources,
|
|
880
|
+
materialBgShared,
|
|
881
|
+
materialBgAssemblyCache,
|
|
882
|
+
bindGroupCounts,
|
|
883
|
+
} = deps;
|
|
884
|
+
const smMaterialHandle = submeshMaterial.materialHandle;
|
|
885
|
+
const materialCacheKey =
|
|
886
|
+
smMaterialHandle === undefined ? undefined : `${materialWorld.identity}:${smMaterialHandle}`;
|
|
887
|
+
const smHasVideoFields = (submeshMaterial.videoTextureFields?.size ?? 0) > 0;
|
|
888
|
+
const smShaderId = submeshMaterial.materialShaderId;
|
|
889
|
+
const smPerShaderBgl =
|
|
890
|
+
smShaderId !== undefined ? runtime.getMaterialBindGroupLayout?.(smShaderId) : undefined;
|
|
891
|
+
const smMaterialBgl = smPerShaderBgl ?? pipelineState.materialBindGroupLayout;
|
|
892
|
+
if (smMaterialHandle !== undefined && !smHasVideoFields) {
|
|
893
|
+
const cached =
|
|
894
|
+
materialCacheKey === undefined ? undefined : materialBgAssemblyCache.get(materialCacheKey);
|
|
895
|
+
if (
|
|
896
|
+
isMaterialBgAssemblyCacheHit(
|
|
897
|
+
cached,
|
|
898
|
+
submeshMaterial,
|
|
899
|
+
smMaterialBgl,
|
|
900
|
+
pipelineState.materialUniformBuffer.buffer,
|
|
901
|
+
skylightResources,
|
|
902
|
+
store.materialResourceEpoch,
|
|
903
|
+
)
|
|
904
|
+
) {
|
|
905
|
+
return cached.bindGroup;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
const smSchema =
|
|
909
|
+
submeshMaterial.materialParamSchema ??
|
|
910
|
+
(smShaderId !== undefined ? runtime.getParamSchema?.(smShaderId) : undefined);
|
|
911
|
+
// The shipped PBR shaders always own the six texture pairs declared by the
|
|
912
|
+
// standard shader artifact. Authored material snapshots may intentionally
|
|
913
|
+
// carry a compact four-field schema because emissive/occlusion are engine
|
|
914
|
+
// injected values, but the runtime PBR BGL still exposes bindings 9..12 for
|
|
915
|
+
// those pairs. Keep the record projection on the shader-owned layout so IBL
|
|
916
|
+
// starts at binding 13 rather than colliding with emissiveSampler.
|
|
917
|
+
const smUserRegionFields =
|
|
918
|
+
smPerShaderBgl === undefined || isStandardPbrMaterialShader(smShaderId)
|
|
919
|
+
? BUILTIN_USER_REGION_TEXTURE_FIELDS
|
|
920
|
+
: userRegionTextureFieldOrder(smSchema);
|
|
921
|
+
let materialResourcesResident = true;
|
|
922
|
+
const smSamplerForField = (field: string | undefined): Sampler => {
|
|
923
|
+
const handle = field === undefined ? undefined : submeshMaterial.samplerHandles?.get(field);
|
|
924
|
+
if (handle === undefined) return pipelineState.defaultSampler;
|
|
925
|
+
const sampler = residentSampler(materialWorld, store, runtime, handle);
|
|
926
|
+
if (sampler === undefined) materialResourcesResident = false;
|
|
927
|
+
return sampler ?? pipelineState.defaultSampler;
|
|
928
|
+
};
|
|
929
|
+
const smBaseEntries: BindGroupEntry[] = [
|
|
930
|
+
{
|
|
931
|
+
binding: 0,
|
|
932
|
+
resource: {
|
|
933
|
+
kind: 'buffer' as const,
|
|
934
|
+
value: {
|
|
935
|
+
buffer: pipelineState.materialUniformBuffer.buffer,
|
|
936
|
+
offset: 0,
|
|
937
|
+
size: materialSlice,
|
|
938
|
+
},
|
|
939
|
+
},
|
|
940
|
+
},
|
|
941
|
+
];
|
|
942
|
+
const smBglPairCount = smUserRegionFields.length;
|
|
943
|
+
for (let fi = 0; fi < smBglPairCount; fi++) {
|
|
944
|
+
const field = smUserRegionFields[fi];
|
|
945
|
+
const samplerBinding = 1 + fi * 2;
|
|
946
|
+
const textureBinding = samplerBinding + 1;
|
|
947
|
+
let smView: TextureView =
|
|
948
|
+
field !== undefined
|
|
949
|
+
? defaultViewForUserRegionField(field, pipelineState)
|
|
950
|
+
: pipelineState.defaultWhiteTextureView;
|
|
951
|
+
const smVideoClip =
|
|
952
|
+
field !== undefined ? submeshMaterial.videoTextureFields?.get(field) : undefined;
|
|
953
|
+
if (smVideoClip !== undefined) {
|
|
954
|
+
const view = videoTextureView(
|
|
955
|
+
materialWorld,
|
|
956
|
+
runtime.dynamicTextureStore,
|
|
957
|
+
runtime,
|
|
958
|
+
entityKey,
|
|
959
|
+
smVideoClip,
|
|
960
|
+
videoHighPerfAvailable,
|
|
961
|
+
);
|
|
962
|
+
if (view !== undefined) smView = view;
|
|
963
|
+
} else {
|
|
964
|
+
const smHandle =
|
|
965
|
+
field === 'emissiveTexture'
|
|
966
|
+
? submeshMaterial.emissiveTexture
|
|
967
|
+
: field === 'occlusionTexture'
|
|
968
|
+
? submeshMaterial.occlusionTexture
|
|
969
|
+
: field !== undefined
|
|
970
|
+
? submeshMaterial.textureHandles?.get(field)
|
|
971
|
+
: undefined;
|
|
972
|
+
if (smHandle !== undefined) {
|
|
973
|
+
const view = residentTextureView(materialWorld, store, runtime, smHandle);
|
|
974
|
+
if (view !== undefined) smView = view;
|
|
975
|
+
else materialResourcesResident = false;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
smBaseEntries.push(
|
|
979
|
+
{
|
|
980
|
+
binding: samplerBinding,
|
|
981
|
+
resource: { kind: 'sampler' as const, value: smSamplerForField(field) },
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
binding: textureBinding,
|
|
985
|
+
resource: { kind: 'textureView' as const, value: smView },
|
|
986
|
+
},
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
let smEmissiveView: TextureView = pipelineState.defaultWhiteTextureView;
|
|
990
|
+
const smEmissiveHandle = submeshMaterial.emissiveTexture;
|
|
991
|
+
if (smEmissiveHandle !== undefined) {
|
|
992
|
+
const view = residentTextureView(materialWorld, store, runtime, smEmissiveHandle);
|
|
993
|
+
if (view !== undefined) smEmissiveView = view;
|
|
994
|
+
else materialResourcesResident = false;
|
|
995
|
+
}
|
|
996
|
+
let smOcclusionView: TextureView = pipelineState.defaultWhiteTextureView;
|
|
997
|
+
const smOcclusionHandle = submeshMaterial.occlusionTexture;
|
|
998
|
+
if (smOcclusionHandle !== undefined) {
|
|
999
|
+
const view = residentTextureView(materialWorld, store, runtime, smOcclusionHandle);
|
|
1000
|
+
if (view !== undefined) smOcclusionView = view;
|
|
1001
|
+
else materialResourcesResident = false;
|
|
1002
|
+
}
|
|
1003
|
+
const smEmissiveAo: EmissiveAoBindGroupResources = {
|
|
1004
|
+
emissiveSampler: smSamplerForField('emissiveTexture'),
|
|
1005
|
+
emissiveView: smEmissiveView,
|
|
1006
|
+
occlusionSampler: smSamplerForField('occlusionTexture'),
|
|
1007
|
+
occlusionView: smOcclusionView,
|
|
1008
|
+
};
|
|
1009
|
+
const smMergedEntries = assembleMaterialWithSkylightEntries(
|
|
1010
|
+
smBaseEntries,
|
|
1011
|
+
skylightResources,
|
|
1012
|
+
smEmissiveAo,
|
|
1013
|
+
);
|
|
1014
|
+
const smBindGroup = getOrCreatePerEntity(
|
|
1015
|
+
materialBgShared,
|
|
1016
|
+
smShaderId ?? '',
|
|
1017
|
+
smMergedEntries.map((e) => extractEntryResourceHandle(e)),
|
|
1018
|
+
'material-shared',
|
|
1019
|
+
() => {
|
|
1020
|
+
const result = runtime.device.createBindGroup({
|
|
1021
|
+
label: 'pbr-material-skylight-bg',
|
|
1022
|
+
layout: smMaterialBgl,
|
|
1023
|
+
entries: smMergedEntries,
|
|
1024
|
+
});
|
|
1025
|
+
if (!result.ok) throw result.error;
|
|
1026
|
+
return result.value;
|
|
1027
|
+
},
|
|
1028
|
+
bindGroupCounts,
|
|
1029
|
+
);
|
|
1030
|
+
if (smMaterialHandle !== undefined && !smHasVideoFields && materialResourcesResident) {
|
|
1031
|
+
if (materialCacheKey !== undefined) {
|
|
1032
|
+
materialBgAssemblyCache.set(materialCacheKey, {
|
|
1033
|
+
material: submeshMaterial,
|
|
1034
|
+
materialResourceEpoch: store.materialResourceEpoch,
|
|
1035
|
+
materialBgl: smMaterialBgl,
|
|
1036
|
+
materialBuffer: pipelineState.materialUniformBuffer.buffer,
|
|
1037
|
+
skylightResources,
|
|
1038
|
+
bindGroup: smBindGroup,
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
return smBindGroup;
|
|
1043
|
+
}
|