@forgeax/engine-render 0.1.20 → 0.1.21
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/README.md +215 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/assembly/device-feature-admission.d.ts +18 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -0
- package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
- package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +21 -18
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +9 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/render-target-host.d.ts +46 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -0
- package/dist/assets/render-asset-port.d.ts.map +1 -1
- package/dist/authoring.mjs +3 -0
- package/dist/authoring.mjs.map +1 -1
- package/dist/capture/cube-views.d.ts +21 -0
- package/dist/capture/cube-views.d.ts.map +1 -0
- package/dist/capture/scheduler.d.ts +54 -0
- package/dist/capture/scheduler.d.ts.map +1 -0
- package/dist/{chunk-4XINDLAY.mjs → chunk-5YADUCA7.mjs} +1552 -1361
- package/dist/chunk-5YADUCA7.mjs.map +1 -0
- package/dist/{chunk-TBQJOK2L.mjs → chunk-6OPXDQ2E.mjs} +364 -51
- package/dist/chunk-6OPXDQ2E.mjs.map +1 -0
- package/dist/{chunk-M2MP4ZOU.mjs → chunk-BXBQQKFQ.mjs} +3 -9
- package/dist/chunk-BXBQQKFQ.mjs.map +1 -0
- package/dist/{chunk-CDTWTHZR.mjs → chunk-FS2KNUQH.mjs} +548 -6
- package/dist/chunk-FS2KNUQH.mjs.map +1 -0
- package/dist/components/camera.d.ts +1 -0
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/cube-camera.d.ts +20 -0
- package/dist/components/cube-camera.d.ts.map +1 -0
- package/dist/components/directional-light.d.ts +11 -2
- package/dist/components/directional-light.d.ts.map +1 -1
- package/dist/components/directional-shadow-filter.d.ts +25 -0
- package/dist/components/directional-shadow-filter.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/reflection-probe.d.ts +17 -0
- package/dist/components/reflection-probe.d.ts.map +1 -0
- package/dist/construct-renderer.mjs +5826 -1003
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +5 -0
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/render.d.ts +141 -93
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/directional-shadow-projection.d.ts +23 -0
- package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
- package/dist/extract/environment.d.ts +14 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/extract/visibility.d.ts.map +1 -1
- package/dist/features/fullscreen.d.ts.map +1 -1
- package/dist/features/targets.d.ts.map +1 -1
- package/dist/features/types.d.ts +10 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/fullscreen-post-process-pass.d.ts +13 -2
- package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +0 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +19 -17
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +4 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/kernel-cache.d.ts +36 -0
- package/dist/ibl/kernel-cache.d.ts.map +1 -0
- package/dist/index.d.ts +28 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +51 -0
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances-derived-bounds.d.ts +50 -0
- package/dist/instances-derived-bounds.d.ts.map +1 -0
- package/dist/internal.mjs +1 -1
- package/dist/light-buffer-layout.d.ts +10 -1
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +54 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +14 -4
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-forward-lane.d.ts +2 -1
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
- package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
- package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
- package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
- package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
- package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
- package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
- package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
- package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
- package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
- package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
- package/dist/pipeline/standard-pipeline.d.ts +4 -13
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline/standard-profile.d.ts +5 -26
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +40 -7
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/point-shadow-inspection.d.ts +21 -0
- package/dist/point-shadow-inspection.d.ts.map +1 -0
- package/dist/record/frame-lighting.d.ts +27 -32
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +28 -14
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts +5 -0
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +10 -4
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
- package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
- package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/index.d.ts +8 -0
- package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
- package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
- package/dist/record/gpu-pass-timing/session.d.ts +43 -0
- package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
- package/dist/record/gpu-timing.d.ts +8 -3
- package/dist/record/gpu-timing.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +22 -1
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +43 -2
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +72 -4
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts +7 -4
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/reflection/filter.d.ts +22 -0
- package/dist/reflection/filter.d.ts.map +1 -0
- package/dist/reflection/gpu-table.d.ts +25 -0
- package/dist/reflection/gpu-table.d.ts.map +1 -0
- package/dist/reflection/projection.d.ts +91 -0
- package/dist/reflection/projection.d.ts.map +1 -0
- package/dist/render-contract.d.ts +49 -7
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts +1 -0
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +42 -2
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +58 -17
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +17 -2
- package/dist/render-system.d.ts.map +1 -1
- package/dist/renderer.d.ts +43 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/scene/render-scene.d.ts +14 -0
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/shadow-atlas.d.ts +3 -3
- package/dist/shadow-atlas.d.ts.map +1 -1
- package/dist/ssao-buffers.d.ts +3 -0
- package/dist/ssao-buffers.d.ts.map +1 -1
- package/dist/targets/contracts.d.ts +66 -0
- package/dist/targets/contracts.d.ts.map +1 -0
- package/dist/targets/graph-projection.d.ts +29 -0
- package/dist/targets/graph-projection.d.ts.map +1 -0
- package/dist/targets/material-source.d.ts +34 -0
- package/dist/targets/material-source.d.ts.map +1 -0
- package/dist/targets/owner.d.ts +32 -0
- package/dist/targets/owner.d.ts.map +1 -0
- package/dist/targets/physical.d.ts +18 -0
- package/dist/targets/physical.d.ts.map +1 -0
- package/dist/targets/readback.d.ts +39 -0
- package/dist/targets/readback.d.ts.map +1 -0
- package/dist/temporal/index.mjs +3 -3
- package/dist/typed-render-graph-primitives.d.ts +1 -1
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/typed-shadow-passes.d.ts +1 -1
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/dist/volume/passes.d.ts +2 -2
- package/dist/volume/passes.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
- package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
- package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
- package/src/__tests__/cluster-binner.unit.test.ts +35 -0
- package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -2
- package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
- package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
- package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
- package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
- package/src/__tests__/cube-camera.integration.test.ts +42 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +73 -0
- package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -3
- package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
- package/src/__tests__/factory-contract.integration.test.ts +255 -29
- package/src/__tests__/fog-component.unit.test.ts +67 -0
- package/src/__tests__/fog.integration.test.ts +86 -0
- package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -9
- package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +17 -1
- package/src/__tests__/gpu-driven-production.integration.test.ts +16 -17
- package/src/__tests__/gpu-driven-view-graph.integration.test.ts +12 -4
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
- package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
- package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
- package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
- package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
- package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
- package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
- package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
- package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
- package/src/__tests__/instances-culling.integration.test.ts +94 -0
- package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
- package/src/__tests__/material-observation.integration.test.ts +101 -0
- package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
- package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
- package/src/__tests__/public-surface.test-d.ts +10 -0
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
- package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
- package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
- package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
- package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
- package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +18 -3
- package/src/__tests__/render-feature-docs.unit.test.ts +1 -1
- package/src/__tests__/render-target-admission.unit.test.ts +80 -0
- package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
- package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
- package/src/__tests__/render-target-material-source.test-d.ts +30 -0
- package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
- package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
- package/src/__tests__/render-target-owner.unit.test.ts +122 -0
- package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
- package/src/__tests__/render-target-public-schema.json +107 -0
- package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
- package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
- package/src/__tests__/render-target-readback.integration.test.ts +90 -0
- package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +48 -0
- package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
- package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
- package/src/__tests__/skin-motion-regression.unit.test.ts +132 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +11 -2
- package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
- package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +232 -0
- package/src/__tests__/standard-clustered-pipeline.unit.test.ts +8 -5
- package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
- package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
- package/src/__tests__/standard-lighting-write.unit.test.ts +377 -0
- package/src/__tests__/standard-lighting.integration.test.ts +67 -0
- package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
- package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
- package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
- package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -38
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
- package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
- package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
- package/src/assembly/device-feature-admission.ts +73 -0
- package/src/assembly/directional-shadow-inspection.ts +122 -0
- package/src/assembly/factory.ts +877 -286
- package/src/assembly/host-contract.ts +25 -0
- package/src/assembly/render-target-host.ts +847 -0
- package/src/assets/asset-decoders.ts +1 -1
- package/src/assets/render-asset-port.ts +7 -1
- package/src/capture/cube-views.ts +69 -0
- package/src/capture/scheduler.ts +265 -0
- package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
- package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
- package/src/components/camera.ts +4 -0
- package/src/components/cube-camera.ts +52 -0
- package/src/components/directional-light.ts +22 -2
- package/src/components/directional-shadow-filter.ts +57 -0
- package/src/components/index.ts +2 -0
- package/src/components/light-helpers.ts +81 -7
- package/src/components/reflection-probe.ts +49 -0
- package/src/environment/frame.ts +6 -24
- package/src/environment/lifecycle.ts +12 -0
- package/src/errors/render.ts +286 -142
- package/src/extract/directional-shadow-projection.ts +61 -0
- package/src/extract/environment.ts +57 -0
- package/src/extract/visibility.ts +25 -1
- package/src/features/fullscreen.ts +3 -0
- package/src/features/targets.ts +4 -1
- package/src/features/types.ts +10 -0
- package/src/fullscreen-post-process-pass.ts +43 -2
- package/src/gpu-driven/batch-topology.ts +1 -0
- package/src/gpu-driven/production-raster.ts +1 -3
- package/src/gpu-scene.ts +8 -1
- package/src/hdrp-buffers.ts +165 -59
- package/src/ibl/IblPipelineCache.ts +11 -0
- package/src/ibl/kernel-cache.ts +88 -0
- package/src/index.ts +148 -0
- package/src/inspection-types.ts +56 -0
- package/src/instances-derived-bounds.ts +171 -0
- package/src/light-buffer-layout.ts +20 -5
- package/src/mesh-material-bindings.ts +132 -0
- package/src/pbr-pipeline.ts +106 -17
- package/src/pipeline/standard-forward-lane.ts +46 -16
- package/src/pipeline/standard-lighting/errors.ts +6 -0
- package/src/pipeline/standard-lighting/graph.ts +157 -0
- package/src/pipeline/standard-lighting/inspection.ts +88 -0
- package/src/pipeline/standard-lighting/layout.ts +31 -0
- package/src/pipeline/standard-lighting/light-frame.ts +34 -0
- package/src/pipeline/standard-lighting/membership.ts +43 -0
- package/src/pipeline/standard-lighting/prepare.ts +37 -0
- package/src/pipeline/standard-lighting/topology.ts +120 -0
- package/src/pipeline/standard-lighting/transport.ts +77 -0
- package/src/pipeline/standard-pipeline.ts +122 -193
- package/src/pipeline/standard-post.ts +26 -7
- package/src/pipeline/standard-profile.ts +17 -47
- package/src/pipeline-spec.ts +84 -21
- package/src/point-shadow-inspection.ts +55 -0
- package/src/record/__tests__/temporal-payload.unit.test.ts +42 -1
- package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
- package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
- package/src/record/frame-lighting.ts +367 -427
- package/src/record/frame-snapshot.ts +35 -27
- package/src/record/frame-targets.ts +17 -0
- package/src/record/frame.ts +261 -74
- package/src/record/gpu-pass-timing/contract.ts +180 -0
- package/src/record/gpu-pass-timing/errors.ts +34 -0
- package/src/record/gpu-pass-timing/index.ts +37 -0
- package/src/record/gpu-pass-timing/parser.ts +97 -0
- package/src/record/gpu-pass-timing/session.ts +938 -0
- package/src/record/gpu-timing.ts +21 -12
- package/src/record/main-pass-geometry.ts +120 -80
- package/src/record/main-pass-material.ts +95 -9
- package/src/record/main-pass-sprite-draws.ts +54 -25
- package/src/record/main-pass.ts +71 -15
- package/src/record/render-context.ts +72 -0
- package/src/record/shadow-pass.ts +17 -28
- package/src/record/skybox-post-pass.ts +20 -4
- package/src/record/typed-frame-graph.ts +893 -44
- package/src/record/view-ubo.ts +63 -28
- package/src/reflection/filter.ts +81 -0
- package/src/reflection/gpu-table.ts +44 -0
- package/src/reflection/projection.ts +281 -0
- package/src/render-contract.ts +76 -5
- package/src/render-graph-primitives.ts +9 -4
- package/src/render-pipeline.ts +117 -2
- package/src/render-system-extract.ts +557 -100
- package/src/render-system.ts +1095 -66
- package/src/renderer.ts +222 -0
- package/src/scene/render-scene.ts +115 -9
- package/src/shadow-atlas.ts +5 -5
- package/src/ssao-buffers.ts +9 -2
- package/src/targets/contracts.ts +182 -0
- package/src/targets/graph-projection.ts +169 -0
- package/src/targets/material-source.ts +143 -0
- package/src/targets/owner.ts +214 -0
- package/src/targets/physical.ts +18 -0
- package/src/targets/readback.ts +153 -0
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +59 -20
- package/src/typed-render-graph-primitives.ts +5 -3
- package/src/typed-shadow-passes.ts +46 -40
- package/src/volume/passes.ts +15 -9
- package/dist/chunk-4XINDLAY.mjs.map +0 -1
- package/dist/chunk-CDTWTHZR.mjs.map +0 -1
- package/dist/chunk-M2MP4ZOU.mjs.map +0 -1
- package/dist/chunk-TBQJOK2L.mjs.map +0 -1
package/src/record/gpu-timing.ts
CHANGED
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
|
|
10
10
|
const MAX_VOLUME_PASSES = 4;
|
|
11
11
|
const QUERY_COUNT = MAX_VOLUME_PASSES * 2;
|
|
12
|
-
const
|
|
13
|
-
const READBACK_BYTES = QUERY_COUNT *
|
|
12
|
+
const QUERY_STRIDE_BYTES = 256;
|
|
13
|
+
const READBACK_BYTES = QUERY_COUNT * QUERY_STRIDE_BYTES;
|
|
14
14
|
const PASS_NAMES = [
|
|
15
15
|
'volume-inject',
|
|
16
16
|
'volume-integrate',
|
|
@@ -34,6 +34,12 @@ function unavailable(reason: string): VolumeTimingObservation {
|
|
|
34
34
|
return Object.freeze({ status: 'unavailable', reason });
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
export interface VolumeTimingTimestampWrites {
|
|
38
|
+
readonly querySet: QuerySet;
|
|
39
|
+
readonly beginningOfPassWriteIndex: number;
|
|
40
|
+
readonly endOfPassWriteIndex: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
37
43
|
/**
|
|
38
44
|
* Renderer-owned timestamp capture for the authored volume graph. Query
|
|
39
45
|
* resources are private to one accepted submit and never cross the receipt
|
|
@@ -109,18 +115,21 @@ export class GpuTimingCapture {
|
|
|
109
115
|
);
|
|
110
116
|
}
|
|
111
117
|
|
|
112
|
-
|
|
118
|
+
recordPass(name: string): VolumeTimingTimestampWrites | undefined {
|
|
113
119
|
const index = PASS_NAMES.indexOf(name as (typeof PASS_NAMES)[number]);
|
|
114
|
-
if (index < 0 || this.#started.has(name)) return;
|
|
120
|
+
if (index < 0 || this.#started.has(name) || this.#discarded) return undefined;
|
|
115
121
|
this.#started.set(name, index);
|
|
116
|
-
|
|
122
|
+
this.#finished.set(name, index);
|
|
123
|
+
return {
|
|
124
|
+
querySet: this.#querySet,
|
|
125
|
+
beginningOfPassWriteIndex: index * 2,
|
|
126
|
+
endOfPassWriteIndex: index * 2 + 1,
|
|
127
|
+
};
|
|
117
128
|
}
|
|
118
129
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
this.#finished.set(name, index);
|
|
123
|
-
encoder.writeTimestamp(this.#querySet, index * 2 + 1);
|
|
130
|
+
skipPass(name: string): void {
|
|
131
|
+
this.#started.delete(name);
|
|
132
|
+
this.#finished.delete(name);
|
|
124
133
|
}
|
|
125
134
|
|
|
126
135
|
resolve(encoder: RhiCommandEncoder): Result<void, RhiError> {
|
|
@@ -176,8 +185,8 @@ export class GpuTimingCapture {
|
|
|
176
185
|
.sort((a, b) => a[1] - b[1])
|
|
177
186
|
.map(([name, index]) => ({
|
|
178
187
|
name,
|
|
179
|
-
begin: values.getBigUint64(index * 2 *
|
|
180
|
-
end: values.getBigUint64((index * 2 + 1) *
|
|
188
|
+
begin: values.getBigUint64(index * 2 * QUERY_STRIDE_BYTES, true),
|
|
189
|
+
end: values.getBigUint64((index * 2 + 1) * QUERY_STRIDE_BYTES, true),
|
|
181
190
|
}));
|
|
182
191
|
if (decoded.some(({ end, begin }) => end < begin)) {
|
|
183
192
|
mapped.value.unmap();
|
|
@@ -17,10 +17,20 @@ import {
|
|
|
17
17
|
GPU_BUFFER_USAGE_STORAGE,
|
|
18
18
|
GPU_BUFFER_USAGE_UNIFORM,
|
|
19
19
|
} from '../gpu-usage';
|
|
20
|
+
import { createHdrpSkinUnifiedBindGroup, getOrCreateHdrpBuffers } from '../hdrp-buffers';
|
|
20
21
|
import type { InstanceBufferCacheEntry } from '../instance-buffer-cache';
|
|
21
22
|
import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from '../materials';
|
|
22
|
-
import {
|
|
23
|
-
|
|
23
|
+
import {
|
|
24
|
+
createPbrSkinMeshBindGroupEntries,
|
|
25
|
+
pbrSkinMeshDynamicOffsets,
|
|
26
|
+
SKIN_MATERIAL_SHADER_ID,
|
|
27
|
+
} from '../pbr-pipeline';
|
|
28
|
+
import {
|
|
29
|
+
renderStateHash,
|
|
30
|
+
standardStorageVariantSet,
|
|
31
|
+
standardTopologyVariantSet,
|
|
32
|
+
variantSetFromVertexLayoutProjection,
|
|
33
|
+
} from '../pipeline-spec';
|
|
24
34
|
import type { PointsLinesRecordPlan } from '../points-lines/record';
|
|
25
35
|
import { POINTS_LINES_MATERIAL_SHADER_ID } from '../points-lines/record';
|
|
26
36
|
import type { RenderRecordPhase } from '../render-contract';
|
|
@@ -30,6 +40,7 @@ import {
|
|
|
30
40
|
geometryRenderStateForTopology,
|
|
31
41
|
isEntityFullyTransparent,
|
|
32
42
|
selectGeometryPipeline,
|
|
43
|
+
selectMaterialGroup2,
|
|
33
44
|
} from './main-pass-material';
|
|
34
45
|
import {
|
|
35
46
|
getOrCreateFromChain,
|
|
@@ -40,7 +51,7 @@ import {
|
|
|
40
51
|
MESH_UBO_FULL_ARRAY_BYTES,
|
|
41
52
|
packInstanceStorageBuffer,
|
|
42
53
|
} from './mesh-ssbo';
|
|
43
|
-
import type { _InternalRenderPipelineContext } from './render-context';
|
|
54
|
+
import type { _InternalRenderPipelineContext, MaterialShaderPipelineEntry } from './render-context';
|
|
44
55
|
import { MATERIAL_PER_ENTITY_STRIDE } from './render-context';
|
|
45
56
|
import { POINTS_LINES_VIEW_SLOT_STRIDE, writePointsLinesViewUbo } from './view-ubo';
|
|
46
57
|
|
|
@@ -66,7 +77,7 @@ type MaterialPipelineLookup = {
|
|
|
66
77
|
readonly layoutProjection: import('@forgeax/engine-geometry').VertexLayoutProjection;
|
|
67
78
|
readonly sampleCount: number;
|
|
68
79
|
readonly colorFormatOverride: GPUTextureFormat | undefined;
|
|
69
|
-
readonly handle:
|
|
80
|
+
readonly handle: MaterialShaderPipelineEntry | null;
|
|
70
81
|
};
|
|
71
82
|
|
|
72
83
|
type GeometryRecordProfileSegment = 'material-bind-groups' | 'pipeline-selection' | 'draw-submit';
|
|
@@ -197,8 +208,13 @@ export function recordGeometryDraws(
|
|
|
197
208
|
validatedOrdered,
|
|
198
209
|
splitLdrSprite,
|
|
199
210
|
viewBindGroup,
|
|
211
|
+
viewBindGroupDynamicOffset = 0,
|
|
200
212
|
} = c;
|
|
201
213
|
const colorFormatOverride = c.transparentColorFormat as GPUTextureFormat | undefined;
|
|
214
|
+
// The prepared Standard topology is the frame authority. A bind-group
|
|
215
|
+
// identity is only a resource result; using it to infer the shader lane
|
|
216
|
+
// would silently fall back to URP when the clustered resource is missing.
|
|
217
|
+
const clusteredLighting = c.standardLighting?.kind === 'clustered';
|
|
202
218
|
// A no-tone frame may still render into the graph-owned rgba16float target
|
|
203
219
|
// (the linear-LDR route). Shader variants must follow the attachment's
|
|
204
220
|
// numeric domain rather than the camera's tone-map switch, otherwise the
|
|
@@ -222,7 +238,6 @@ export function recordGeometryDraws(
|
|
|
222
238
|
const profilePhase = c.profilePhase;
|
|
223
239
|
const materialGroup1DynamicOffsets = new Uint32Array(1);
|
|
224
240
|
const meshGroup2DynamicOffsets = [0];
|
|
225
|
-
const skinGroup2DynamicOffsets = [0, 0];
|
|
226
241
|
let lastStencilReference: number | null = null;
|
|
227
242
|
// feat-20260625-refactor-sprite-as-transparent-mesh M3 / w14 (D-7):
|
|
228
243
|
// sprite PSO selection no longer maintains a dedicated tag — the
|
|
@@ -246,7 +261,7 @@ export function recordGeometryDraws(
|
|
|
246
261
|
variantSet: string | undefined,
|
|
247
262
|
colorFormat: GPUTextureFormat | undefined,
|
|
248
263
|
layoutProjection: import('@forgeax/engine-geometry').VertexLayoutProjection,
|
|
249
|
-
):
|
|
264
|
+
): MaterialShaderPipelineEntry | null => {
|
|
250
265
|
const renderStateKey = renderStateHash(renderState);
|
|
251
266
|
const shaderLookupCache = materialPipelineLookupCache.get(materialShaderId);
|
|
252
267
|
const cachedLookups = shaderLookupCache?.get(renderStateKey);
|
|
@@ -278,7 +293,7 @@ export function recordGeometryDraws(
|
|
|
278
293
|
}
|
|
279
294
|
const resolvedVariantSet = resolvedVariantSetResult.value;
|
|
280
295
|
const resolvePipeline = () =>
|
|
281
|
-
runtime.
|
|
296
|
+
runtime.getMaterialShaderPipelineEntry?.(
|
|
282
297
|
materialShaderId,
|
|
283
298
|
isHdrTarget,
|
|
284
299
|
renderState,
|
|
@@ -340,7 +355,7 @@ export function recordGeometryDraws(
|
|
|
340
355
|
// Points/Lines share the Standard geometry pass. Their retained source
|
|
341
356
|
// is prepared once by the renderer owner, while this loop remains the
|
|
342
357
|
// sole pass/draw submission owner and preserves the authored topology.
|
|
343
|
-
const pointsLinesSubmission = c.pointsLines?.prepare(entry,
|
|
358
|
+
const pointsLinesSubmission = c.pointsLines?.prepare(entry, clusteredLighting);
|
|
344
359
|
if (entry.source.pointsLines !== undefined && pointsLinesSubmission?.plan.drawCount !== 1)
|
|
345
360
|
continue;
|
|
346
361
|
|
|
@@ -399,7 +414,7 @@ export function recordGeometryDraws(
|
|
|
399
414
|
entry.source.entityKey,
|
|
400
415
|
entry.world ?? c.world,
|
|
401
416
|
);
|
|
402
|
-
const
|
|
417
|
+
const pointsLinesPipelineEntry = resolveMaterialPipeline(
|
|
403
418
|
POINTS_LINES_MATERIAL_SHADER_ID,
|
|
404
419
|
{
|
|
405
420
|
...pointsLinesMaterial.renderState,
|
|
@@ -411,7 +426,8 @@ export function recordGeometryDraws(
|
|
|
411
426
|
colorFormatOverride,
|
|
412
427
|
pointsLinesSubmission.layoutProjection,
|
|
413
428
|
);
|
|
414
|
-
if (
|
|
429
|
+
if (pointsLinesPipelineEntry === null) continue;
|
|
430
|
+
const pointsLinesPipeline = pointsLinesPipelineEntry.pipeline;
|
|
415
431
|
if (pipelineState.pointsLinesViewBuffer === undefined) continue;
|
|
416
432
|
writePointsLinesViewUbo(
|
|
417
433
|
runtime.device.queue,
|
|
@@ -426,9 +442,9 @@ export function recordGeometryDraws(
|
|
|
426
442
|
pass.setBindGroup(
|
|
427
443
|
0,
|
|
428
444
|
viewBindGroup as BindGroup,
|
|
429
|
-
new Uint32Array([i * POINTS_LINES_VIEW_SLOT_STRIDE]),
|
|
445
|
+
new Uint32Array([0, i * POINTS_LINES_VIEW_SLOT_STRIDE]),
|
|
430
446
|
0,
|
|
431
|
-
|
|
447
|
+
2,
|
|
432
448
|
);
|
|
433
449
|
pass.setPipeline(pointsLinesPipeline);
|
|
434
450
|
pass.setVertexBuffer(0, pointsLinesSubmission.vertexBuffer);
|
|
@@ -444,7 +460,7 @@ export function recordGeometryDraws(
|
|
|
444
460
|
resolveGeometryInstancesBindGroup(c, identityInstanceBuffer),
|
|
445
461
|
);
|
|
446
462
|
recordPointsLinesDraw(pass, pointsLinesSubmission.plan);
|
|
447
|
-
pass.setBindGroup(0, viewBindGroup as BindGroup, [0]);
|
|
463
|
+
pass.setBindGroup(0, viewBindGroup as BindGroup, [viewBindGroupDynamicOffset, 0]);
|
|
448
464
|
continue;
|
|
449
465
|
}
|
|
450
466
|
|
|
@@ -474,11 +490,12 @@ export function recordGeometryDraws(
|
|
|
474
490
|
const instanceDraws = resolveGeometryInstanceBuffer(c, entry, identityInstanceDraws);
|
|
475
491
|
if (instanceDraws === null) continue;
|
|
476
492
|
|
|
477
|
-
// feat-20260611 R2 / M8 / w28 (IS-14): skin entries need a
|
|
493
|
+
// feat-20260611 R2 / M8 / w28 (IS-14): skin entries need a 3-binding
|
|
478
494
|
// group(2) BG matching `pbr-skin-pl` (binding 0 mesh-array UBO +
|
|
479
|
-
// binding 1 palette UBO
|
|
495
|
+
// binding 1 current palette UBO + binding 2 previous palette UBO).
|
|
496
|
+
// Building this here -- not in the
|
|
480
497
|
// `meshBindGroup` factory above -- because the binding-shape
|
|
481
|
-
// (1-entry vs
|
|
498
|
+
// (1-entry vs 3-entry) is per-entry, not per-frame. URP / HDRP
|
|
482
499
|
// entries keep using `meshGroup2` (1-entry mesh-array or HDRP
|
|
483
500
|
// unified). The skin-variant cache key includes both buffer
|
|
484
501
|
// identities so a future allocator-driven palette buffer rotation
|
|
@@ -489,7 +506,7 @@ export function recordGeometryDraws(
|
|
|
489
506
|
// BGL-build failure), AND (b) the skin PSO cache returns a non-null
|
|
490
507
|
// pipeline for this entry. Without (b), the per-submesh selector
|
|
491
508
|
// below falls back to URP `standardPipeline` (`pbr-pl` layout,
|
|
492
|
-
// 1-entry mesh-array BGL); binding the
|
|
509
|
+
// 1-entry mesh-array BGL); binding the 3-entry skin BG against
|
|
493
510
|
// that pipeline reproduces the exact `pbr-mesh-array-bgl ... does
|
|
494
511
|
// not match layout pbr-skin-mesh-array-bgl` device error R1
|
|
495
512
|
// captured. Mirrors the uniform null skip-draw pattern (M6-T1).
|
|
@@ -517,28 +534,40 @@ export function recordGeometryDraws(
|
|
|
517
534
|
// and walks 0, 1536, 3072, ... on the storage path.
|
|
518
535
|
const skinAllocator = pipelineState.skinPaletteAllocator;
|
|
519
536
|
const skinSlice = entry.source.skin;
|
|
537
|
+
const clusteredSkin = clusteredLighting;
|
|
538
|
+
const skinMeshBindGroupLayout = clusteredSkin
|
|
539
|
+
? pipelineState.hdrpSkinMeshBindGroupLayout
|
|
540
|
+
: pipelineState.pbrSkinMeshBindGroupLayout;
|
|
541
|
+
const hdrpSkinBuffers =
|
|
542
|
+
isSkinEntry && clusteredSkin
|
|
543
|
+
? getOrCreateHdrpBuffers(runtime, frameState.installedPipelineConfig?.clusterGrid)
|
|
544
|
+
: null;
|
|
520
545
|
const skinResources =
|
|
521
546
|
isSkinEntry &&
|
|
522
|
-
|
|
547
|
+
skinMeshBindGroupLayout !== null &&
|
|
523
548
|
skinAllocator !== null &&
|
|
524
|
-
skinSlice !== undefined
|
|
549
|
+
skinSlice !== undefined &&
|
|
550
|
+
(!clusteredSkin || hdrpSkinBuffers !== null)
|
|
525
551
|
? {
|
|
526
|
-
meshArrayBgl:
|
|
552
|
+
meshArrayBgl: skinMeshBindGroupLayout,
|
|
527
553
|
paletteBuffer: skinSlice.buffer,
|
|
528
554
|
paletteBindingWindowBytes: skinAllocator.bindingWindowBytes,
|
|
555
|
+
hdrpBuffers: hdrpSkinBuffers,
|
|
529
556
|
}
|
|
530
557
|
: null;
|
|
531
558
|
// Probe the skin PSO cache up front so we can decide whether to swap
|
|
532
|
-
// to the
|
|
559
|
+
// to the skin BG. The same probe + selector is repeated in
|
|
533
560
|
// the per-submesh loop below (the loop's variantSet derivation is
|
|
534
561
|
// identical -- skin shader registers a single all-true variant so
|
|
535
562
|
// the canonical empty-key rule applies on HDRP and the URP key is
|
|
536
563
|
// the explicit expanded form, mirroring the standard PBR path).
|
|
537
564
|
const skinVariantSetResult = variantSetFromVertexLayoutProjection(
|
|
538
565
|
entry.mesh.layoutProjection,
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
566
|
+
standardTopologyVariantSet(
|
|
567
|
+
c.standardLighting,
|
|
568
|
+
runtime.device.caps.storageBuffer,
|
|
569
|
+
entry.mesh.layoutProjection.attributes.some((attribute) => attribute.key === 'color'),
|
|
570
|
+
),
|
|
542
571
|
);
|
|
543
572
|
if (!skinVariantSetResult.ok) runtime.errorRegistry.fire(skinVariantSetResult.error);
|
|
544
573
|
const skinVariantSet = skinVariantSetResult.ok ? skinVariantSetResult.value : undefined;
|
|
@@ -579,45 +608,47 @@ export function recordGeometryDraws(
|
|
|
579
608
|
const skinMissesBefore = bindGroupCounts.createBindGroup;
|
|
580
609
|
const skinBindGroup: BindGroup = getOrCreateFromChain(
|
|
581
610
|
frameState.meshBindGroupCache,
|
|
582
|
-
[
|
|
611
|
+
[
|
|
612
|
+
pipelineState.meshStorageBuffer.buffer,
|
|
613
|
+
skinResources.paletteBuffer,
|
|
614
|
+
...(skinResources.hdrpBuffers === null
|
|
615
|
+
? []
|
|
616
|
+
: [
|
|
617
|
+
skinResources.hdrpBuffers.lightDataBuffer,
|
|
618
|
+
skinResources.hdrpBuffers.clusterGridBuffer,
|
|
619
|
+
skinResources.hdrpBuffers.lightIndexListBuffer,
|
|
620
|
+
skinResources.hdrpBuffers.clusterUniformBuffer,
|
|
621
|
+
]),
|
|
622
|
+
],
|
|
583
623
|
'pbr-skin-mesh',
|
|
584
624
|
() => {
|
|
625
|
+
if (skinResources.hdrpBuffers !== null) {
|
|
626
|
+
const result = createHdrpSkinUnifiedBindGroup(
|
|
627
|
+
runtime,
|
|
628
|
+
skinResources.hdrpBuffers,
|
|
629
|
+
skinResources.meshArrayBgl,
|
|
630
|
+
pipelineState.meshStorageBuffer.buffer,
|
|
631
|
+
skinResources.paletteBuffer,
|
|
632
|
+
skinResources.paletteBindingWindowBytes,
|
|
633
|
+
);
|
|
634
|
+
if (result === null) {
|
|
635
|
+
throw new RhiError({
|
|
636
|
+
code: 'webgpu-runtime-error',
|
|
637
|
+
expected: 'HDRP clustered skin BindGroup creation succeeds',
|
|
638
|
+
hint: 'inspect prior errorRegistry events for createBindGroup failure detail',
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
return result;
|
|
642
|
+
}
|
|
585
643
|
const result = runtime.device.createBindGroup({
|
|
586
644
|
label: 'pbr-skin-mesh-bg',
|
|
587
645
|
layout: skinResources.meshArrayBgl,
|
|
588
|
-
entries:
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
buffer: pipelineState.meshStorageBuffer.buffer,
|
|
595
|
-
offset: 0,
|
|
596
|
-
size: meshBindSize,
|
|
597
|
-
},
|
|
598
|
-
},
|
|
599
|
-
},
|
|
600
|
-
{
|
|
601
|
-
binding: 1,
|
|
602
|
-
resource: {
|
|
603
|
-
kind: 'buffer',
|
|
604
|
-
value: {
|
|
605
|
-
buffer: skinResources.paletteBuffer,
|
|
606
|
-
offset: 0,
|
|
607
|
-
// M6 SSOT: static BG entry size (= MAX_JOINTS * 64 =
|
|
608
|
-
// 16320 B) sourced from the allocator. The per-draw
|
|
609
|
-
// window slides via `group2DynamicOffsets[1]`
|
|
610
|
-
// (= entry.source.skin.byteOffset) so this size
|
|
611
|
-
// stays at the worst case across all skin entries
|
|
612
|
-
// -- one BG covers every skinned draw in the frame
|
|
613
|
-
// (m3-1b miss=1 + hit=N-1 contract). The allocator
|
|
614
|
-
// guarantees `buffer.size >= byteOffset + this size`
|
|
615
|
-
// so dynOffset[1] passes WebGPU validation.
|
|
616
|
-
size: skinResources.paletteBindingWindowBytes,
|
|
617
|
-
},
|
|
618
|
-
},
|
|
619
|
-
},
|
|
620
|
-
],
|
|
646
|
+
entries: createPbrSkinMeshBindGroupEntries(
|
|
647
|
+
pipelineState.meshStorageBuffer.buffer,
|
|
648
|
+
meshBindSize,
|
|
649
|
+
skinResources.paletteBuffer,
|
|
650
|
+
skinResources.paletteBindingWindowBytes,
|
|
651
|
+
),
|
|
621
652
|
});
|
|
622
653
|
if (!result.ok) throw result.error;
|
|
623
654
|
return result.value;
|
|
@@ -634,9 +665,10 @@ export function recordGeometryDraws(
|
|
|
634
665
|
// Replaces the prior PR #353 hard-coded `0` second slot -- every
|
|
635
666
|
// skin entry now points the palette window at its own slice while
|
|
636
667
|
// sharing the worst-case BG entry size above.
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
668
|
+
group2DynamicOffsets = pbrSkinMeshDynamicOffsets(
|
|
669
|
+
i * MESH_PER_ENTITY_STRIDE,
|
|
670
|
+
entry.source.skin?.byteOffset ?? 0,
|
|
671
|
+
);
|
|
640
672
|
} else if (isSkinEntry) {
|
|
641
673
|
// Skin entry but skin PSO not ready (cache miss / async build pending,
|
|
642
674
|
// or skin pipeline layout failed at boot). Skip the draw rather than
|
|
@@ -778,6 +810,8 @@ export function recordGeometryDraws(
|
|
|
778
810
|
: geometryRenderStateForTopology(smTopology, submeshMaterial.renderState);
|
|
779
811
|
const pipelineRenderState = geometryRenderStateForPass(basePipelineRenderState, passKind);
|
|
780
812
|
let smPipelineHandle: typeof pipelineState.unlitPipeline;
|
|
813
|
+
let materialGroup2Contract: 'mesh' | 'skin' | 'cluster' | 'skin-cluster' | undefined;
|
|
814
|
+
let materialPipelineEntry: MaterialShaderPipelineEntry | null = null;
|
|
781
815
|
if (smMaterialShaderId === undefined || smMaterialShaderId === 'forgeax::default-unlit') {
|
|
782
816
|
const unlitShaderId = smMaterialShaderId ?? 'forgeax::default-unlit';
|
|
783
817
|
const unlitProjectionVariantResult = variantSetFromVertexLayoutProjection(
|
|
@@ -789,9 +823,10 @@ export function recordGeometryDraws(
|
|
|
789
823
|
continue;
|
|
790
824
|
}
|
|
791
825
|
const unlitHasColor = unlitProjectionVariantResult.value === 'VERTEX_COLOR_AVAILABLE=true';
|
|
792
|
-
const unlitVariantSet =
|
|
793
|
-
|
|
794
|
-
|
|
826
|
+
const unlitVariantSet = standardStorageVariantSet(
|
|
827
|
+
runtime.device.caps.storageBuffer,
|
|
828
|
+
unlitHasColor,
|
|
829
|
+
);
|
|
795
830
|
const unlitRsp = resolveMaterialPipeline(
|
|
796
831
|
unlitShaderId,
|
|
797
832
|
pipelineRenderState,
|
|
@@ -801,8 +836,9 @@ export function recordGeometryDraws(
|
|
|
801
836
|
colorFormatOverride,
|
|
802
837
|
entry.mesh.layoutProjection,
|
|
803
838
|
);
|
|
839
|
+
materialPipelineEntry = unlitRsp;
|
|
804
840
|
smPipelineHandle =
|
|
805
|
-
unlitRsp ??
|
|
841
|
+
unlitRsp?.pipeline ??
|
|
806
842
|
(colorFormatOverride === undefined
|
|
807
843
|
? selectGeometryPipeline(pipelineState, isHdrTarget, msaaActive)
|
|
808
844
|
: null);
|
|
@@ -829,11 +865,11 @@ export function recordGeometryDraws(
|
|
|
829
865
|
// VERTEX_COLOR_AVAILABLE=false axis, so retain the two capability
|
|
830
866
|
// axes explicitly or the selector would silently choose the URP
|
|
831
867
|
// group(2) layout for an HDRP cluster bind group.
|
|
832
|
-
const capabilityVariantSet =
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
868
|
+
const capabilityVariantSet = standardTopologyVariantSet(
|
|
869
|
+
c.standardLighting,
|
|
870
|
+
runtime.device.caps.storageBuffer,
|
|
871
|
+
hasVertexColor,
|
|
872
|
+
);
|
|
837
873
|
// Sprite's base request must retain the boot-selected artifact. Only
|
|
838
874
|
// SpriteInstances uses the explicit empty key for the
|
|
839
875
|
// PER_INSTANCE_REGION=true variant; synthesizing the generic PBR
|
|
@@ -877,7 +913,8 @@ export function recordGeometryDraws(
|
|
|
877
913
|
// build resolves. The pre-loop skin-PSO probe still skips the
|
|
878
914
|
// entire entry on first-submesh probe miss; this site only
|
|
879
915
|
// fires on per-submesh topology variance miss.
|
|
880
|
-
|
|
916
|
+
materialPipelineEntry = cachedPipeline;
|
|
917
|
+
smPipelineHandle = cachedPipeline?.pipeline ?? null;
|
|
881
918
|
} else {
|
|
882
919
|
smPipelineHandle = selectGeometryPipeline(pipelineState, isHdrTarget, msaaActive);
|
|
883
920
|
}
|
|
@@ -890,16 +927,16 @@ export function recordGeometryDraws(
|
|
|
890
927
|
// ordinary mesh group instead; choosing one group for the whole pass
|
|
891
928
|
// makes Dawn reject an otherwise valid unlit pipeline and invalidates
|
|
892
929
|
// the command buffer before it reaches the surface.
|
|
893
|
-
const usesStandardClusterBindings = smMaterialShaderId === 'forgeax::default-standard-pbr';
|
|
894
930
|
if (!isSkinEntry) {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
931
|
+
materialGroup2Contract = materialPipelineEntry?.group2Contract;
|
|
932
|
+
if (materialGroup2Contract === undefined) continue;
|
|
933
|
+
const selectedGroup = selectMaterialGroup2(
|
|
934
|
+
meshGroup2,
|
|
935
|
+
meshBindGroup,
|
|
936
|
+
materialGroup2Contract,
|
|
937
|
+
);
|
|
938
|
+
if (selectedGroup === null) continue;
|
|
939
|
+
group2BindGroup = selectedGroup;
|
|
903
940
|
}
|
|
904
941
|
pass.setBindGroup(2, group2BindGroup, group2DynamicOffsets);
|
|
905
942
|
|
|
@@ -945,6 +982,9 @@ function resolveGeometryInstanceBuffer(
|
|
|
945
982
|
const { runtime, pipelineState, frameState } = c;
|
|
946
983
|
const inst = entry.source.instances;
|
|
947
984
|
if (inst === undefined) return identityInstanceDraws;
|
|
985
|
+
// A present, empty Instances array means zero draws. Do not fall back to
|
|
986
|
+
// the shared identity buffer, which would silently render one instance.
|
|
987
|
+
if (inst.instanceCount === 0) return [];
|
|
948
988
|
let instanceBuffer: Buffer = pipelineState.identityInstanceBuffer;
|
|
949
989
|
let instanceCount = 1;
|
|
950
990
|
{
|
|
@@ -40,9 +40,16 @@ import {
|
|
|
40
40
|
type SkylightBindGroupResources,
|
|
41
41
|
type TransmissionBindGroupResources,
|
|
42
42
|
} from '../ibl/skylight-bind-group';
|
|
43
|
+
import type { PipelineGroup2Contract } from '../pbr-pipeline';
|
|
43
44
|
import { isStandardPbrMaterialShader } from '../pbr-pipeline';
|
|
44
45
|
import { deriveTextureExtent } from '../render-data';
|
|
45
46
|
import type { MaterialSnapshot } from '../render-system-extract';
|
|
47
|
+
import type { RenderTargetTextureSource } from '../targets/contracts';
|
|
48
|
+
import {
|
|
49
|
+
type RenderTargetMaterialSourceBinding,
|
|
50
|
+
resolveRenderTargetMaterialSource,
|
|
51
|
+
} from '../targets/material-source';
|
|
52
|
+
import type { StandardReflectionProbeBinding } from './frame-lighting';
|
|
46
53
|
import type { BindGroupCounts, MaterialBgAssemblyCacheEntry } from './frame-snapshot';
|
|
47
54
|
import { extractEntryResourceHandle, getOrCreatePerEntity } from './mesh-ssbo';
|
|
48
55
|
import {
|
|
@@ -51,6 +58,23 @@ import {
|
|
|
51
58
|
STANDARD_PBR_UBO_SIZE,
|
|
52
59
|
} from './render-context';
|
|
53
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Resolve the group(2) resource layout from the material shader contract.
|
|
63
|
+
* Standard clustered PBR consumes the unified cluster bind group; every other
|
|
64
|
+
* material consumes the ordinary mesh bind group. Missing ordinary resources
|
|
65
|
+
* remain missing so the caller can skip the draw rather than violate layout
|
|
66
|
+
* compatibility by binding a cluster group.
|
|
67
|
+
*/
|
|
68
|
+
export function selectMaterialGroup2(
|
|
69
|
+
clusterGroup: BindGroup | null,
|
|
70
|
+
meshGroup: BindGroup | null,
|
|
71
|
+
group2Contract: PipelineGroup2Contract,
|
|
72
|
+
): BindGroup | null {
|
|
73
|
+
if (group2Contract === 'cluster') return clusterGroup;
|
|
74
|
+
if (group2Contract === 'mesh') return meshGroup;
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
54
78
|
// Param schemas are immutable runtime contracts: the shader registry installs
|
|
55
79
|
// them once and material snapshots only retain the same array reference. Keep
|
|
56
80
|
// the expensive pure derivation on that identity so the per-submesh record
|
|
@@ -412,6 +436,21 @@ const DEFAULT_STANDARD_TEXTURE_COORDINATES = new Float32Array([
|
|
|
412
436
|
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,
|
|
413
437
|
]);
|
|
414
438
|
|
|
439
|
+
export interface StandardReflectionProbeMaterialProjection {
|
|
440
|
+
readonly probeIndex: number | undefined;
|
|
441
|
+
readonly fallbackToSkylight: boolean;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/** Projects the selected scene row into the Standard material lane. */
|
|
445
|
+
export function projectReflectionProbeMaterialBinding(
|
|
446
|
+
binding: StandardReflectionProbeBinding,
|
|
447
|
+
): StandardReflectionProbeMaterialProjection {
|
|
448
|
+
return {
|
|
449
|
+
probeIndex: binding.probeIndex,
|
|
450
|
+
fallbackToSkylight: binding.useSkylight,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
415
454
|
/** Derives the logical-content UV scale for an uploaded material texture. */
|
|
416
455
|
export function materialTextureUvScale(
|
|
417
456
|
texture: Pick<TextureAsset, 'shape' | 'format'> | undefined,
|
|
@@ -433,6 +472,18 @@ function materialTextureForField(
|
|
|
433
472
|
return material.textureHandles?.get(field);
|
|
434
473
|
}
|
|
435
474
|
|
|
475
|
+
/** Resolve a renderer-local target source without entering AssetRegistry. */
|
|
476
|
+
export function materialRenderTargetSourceForField(
|
|
477
|
+
material: MaterialSnapshot,
|
|
478
|
+
field: string,
|
|
479
|
+
resolveSource?: RenderSystemRuntime['resolveRenderTargetTextureSource'],
|
|
480
|
+
): RenderTargetMaterialSourceBinding | undefined {
|
|
481
|
+
const source = material.textureSources?.get(field) as RenderTargetTextureSource | undefined;
|
|
482
|
+
return source === undefined
|
|
483
|
+
? undefined
|
|
484
|
+
: (resolveSource?.(source) ?? resolveRenderTargetMaterialSource(source));
|
|
485
|
+
}
|
|
486
|
+
|
|
436
487
|
/**
|
|
437
488
|
* Appends the engine-owned scale for every built-in material texture binding.
|
|
438
489
|
* Asset dimensions remain logical; this is the sole record-stage projection
|
|
@@ -583,7 +634,15 @@ export function userRegionTextureFieldOrder(
|
|
|
583
634
|
export function defaultViewForUserRegionField(
|
|
584
635
|
field: string,
|
|
585
636
|
pipelineState: PipelineState,
|
|
637
|
+
schema?: readonly ParamSchemaEntry[],
|
|
586
638
|
): TextureView {
|
|
639
|
+
const parameter = schema?.find((entry) => entry.name === field);
|
|
640
|
+
if (parameter?.type === 'texture_cube') {
|
|
641
|
+
// The renderer already owns a valid white cube for the Skylight fallback.
|
|
642
|
+
// Use it until a receipt-promoted RenderTarget source becomes available;
|
|
643
|
+
// binding a 2D view here would invalidate the custom cube material BGL.
|
|
644
|
+
return pipelineState.skylightFallback?.prefilterView ?? pipelineState.defaultWhiteTextureView;
|
|
645
|
+
}
|
|
587
646
|
if (field === 'normalTexture') return pipelineState.defaultNormalTextureView;
|
|
588
647
|
if (field === 'baseColorTexture') return pipelineState.fallbackTextureView;
|
|
589
648
|
return pipelineState.defaultWhiteTextureView;
|
|
@@ -885,6 +944,11 @@ export interface PerSubmeshMaterialBgDeps {
|
|
|
885
944
|
readonly materialSlice: number;
|
|
886
945
|
readonly videoHighPerfAvailable: boolean;
|
|
887
946
|
readonly skylightResources: SkylightBindGroupResources;
|
|
947
|
+
readonly resolveRenderTargetTextureSource?: RenderSystemRuntime['resolveRenderTargetTextureSource'];
|
|
948
|
+
readonly resolveReflectionProbeResources?: (
|
|
949
|
+
materialWorld: World,
|
|
950
|
+
entityKey: number,
|
|
951
|
+
) => SkylightBindGroupResources | undefined;
|
|
888
952
|
readonly materialBgShared: Map<string, WeakMap<object, unknown>>;
|
|
889
953
|
/** Cross-frame final BG reuse keyed by the stable source material handle. */
|
|
890
954
|
readonly materialBgAssemblyCache: Map<string, MaterialBgAssemblyCacheEntry>;
|
|
@@ -932,11 +996,15 @@ export function buildPerSubmeshMaterialBg(
|
|
|
932
996
|
materialSlice,
|
|
933
997
|
videoHighPerfAvailable,
|
|
934
998
|
skylightResources,
|
|
999
|
+
resolveRenderTargetTextureSource,
|
|
1000
|
+
resolveReflectionProbeResources,
|
|
935
1001
|
materialBgShared,
|
|
936
1002
|
materialBgAssemblyCache,
|
|
937
1003
|
transmissionBackdropView,
|
|
938
1004
|
bindGroupCounts,
|
|
939
1005
|
} = deps;
|
|
1006
|
+
const effectiveSkylightResources =
|
|
1007
|
+
resolveReflectionProbeResources?.(materialWorld, entityKey) ?? skylightResources;
|
|
940
1008
|
const smMaterialHandle = submeshMaterial.materialHandle;
|
|
941
1009
|
const materialCacheKey =
|
|
942
1010
|
smMaterialHandle === undefined ? undefined : `${materialWorld.identity}:${smMaterialHandle}`;
|
|
@@ -955,7 +1023,7 @@ export function buildPerSubmeshMaterialBg(
|
|
|
955
1023
|
submeshMaterial,
|
|
956
1024
|
smMaterialBgl,
|
|
957
1025
|
pipelineState.materialUniformBuffer.buffer,
|
|
958
|
-
|
|
1026
|
+
effectiveSkylightResources,
|
|
959
1027
|
store.materialResourceEpoch,
|
|
960
1028
|
transmissionBackdropView,
|
|
961
1029
|
)
|
|
@@ -1003,11 +1071,25 @@ export function buildPerSubmeshMaterialBg(
|
|
|
1003
1071
|
const textureBinding = samplerBinding + 1;
|
|
1004
1072
|
let smView: TextureView =
|
|
1005
1073
|
field !== undefined
|
|
1006
|
-
? defaultViewForUserRegionField(field, pipelineState)
|
|
1074
|
+
? defaultViewForUserRegionField(field, pipelineState, smSchema)
|
|
1007
1075
|
: pipelineState.defaultWhiteTextureView;
|
|
1008
1076
|
const smVideoClip =
|
|
1009
1077
|
field !== undefined ? submeshMaterial.videoTextureFields?.get(field) : undefined;
|
|
1010
|
-
|
|
1078
|
+
const smTargetSource =
|
|
1079
|
+
field === undefined
|
|
1080
|
+
? undefined
|
|
1081
|
+
: materialRenderTargetSourceForField(
|
|
1082
|
+
submeshMaterial,
|
|
1083
|
+
field,
|
|
1084
|
+
resolveRenderTargetTextureSource,
|
|
1085
|
+
);
|
|
1086
|
+
if (smTargetSource !== undefined) {
|
|
1087
|
+
// The Renderer host resolves the generation-checked physical view. A
|
|
1088
|
+
// candidate is never exposed here; until its matching FrameReceipt
|
|
1089
|
+
// completes, the material remains on the neutral fallback.
|
|
1090
|
+
if (smTargetSource.textureView !== undefined) smView = smTargetSource.textureView;
|
|
1091
|
+
else materialResourcesResident = false;
|
|
1092
|
+
} else if (smVideoClip !== undefined) {
|
|
1011
1093
|
const view = videoTextureView(
|
|
1012
1094
|
materialWorld,
|
|
1013
1095
|
runtime.dynamicTextureStore,
|
|
@@ -1049,12 +1131,16 @@ export function buildPerSubmeshMaterialBg(
|
|
|
1049
1131
|
// authored UV textures and is not a backdrop sampler.
|
|
1050
1132
|
const transmissionSampler =
|
|
1051
1133
|
transmissionBackdropView != null
|
|
1052
|
-
?
|
|
1134
|
+
? effectiveSkylightResources.prefilterSampler
|
|
1053
1135
|
: pipelineState.defaultSampler;
|
|
1054
|
-
const smMergedEntries = assembleMaterialWithSkylightEntries(
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1136
|
+
const smMergedEntries = assembleMaterialWithSkylightEntries(
|
|
1137
|
+
smBaseEntries,
|
|
1138
|
+
effectiveSkylightResources,
|
|
1139
|
+
{
|
|
1140
|
+
sampler: transmissionSampler,
|
|
1141
|
+
...(transmissionBackdropView === undefined ? {} : { backdropView: transmissionBackdropView }),
|
|
1142
|
+
} satisfies TransmissionBindGroupResources,
|
|
1143
|
+
);
|
|
1058
1144
|
const createBindGroup = (): BindGroup => {
|
|
1059
1145
|
const result = runtime.device.createBindGroup({
|
|
1060
1146
|
label: 'pbr-material-skylight-bg',
|
|
@@ -1086,7 +1172,7 @@ export function buildPerSubmeshMaterialBg(
|
|
|
1086
1172
|
materialResourceEpoch: store.materialResourceEpoch,
|
|
1087
1173
|
materialBgl: smMaterialBgl,
|
|
1088
1174
|
materialBuffer: pipelineState.materialUniformBuffer.buffer,
|
|
1089
|
-
skylightResources,
|
|
1175
|
+
skylightResources: effectiveSkylightResources,
|
|
1090
1176
|
bindGroup: smBindGroup,
|
|
1091
1177
|
});
|
|
1092
1178
|
}
|