@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
|
@@ -3,12 +3,18 @@ import {
|
|
|
3
3
|
type CompiledRenderGraph,
|
|
4
4
|
type GraphResourceResolver,
|
|
5
5
|
RenderGraphBuilder,
|
|
6
|
+
RenderGraphError,
|
|
7
|
+
type RenderGraphPassInstrumentation,
|
|
8
|
+
type RenderGraphPassInstrumentationScope,
|
|
6
9
|
} from '@forgeax/engine-render-graph';
|
|
7
10
|
import type {
|
|
11
|
+
BindGroup,
|
|
8
12
|
BindGroupLayout,
|
|
13
|
+
Buffer,
|
|
9
14
|
CommandBuffer,
|
|
10
15
|
RenderPipeline,
|
|
11
16
|
RhiCommandEncoder,
|
|
17
|
+
Sampler,
|
|
12
18
|
Texture,
|
|
13
19
|
TextureFormat,
|
|
14
20
|
TextureView,
|
|
@@ -28,10 +34,13 @@ import type {
|
|
|
28
34
|
RenderFeatureGraphTargetResolver,
|
|
29
35
|
} from '../features/render-graph-raster';
|
|
30
36
|
import { isRenderFeatureTargetHandle } from '../features/targets';
|
|
37
|
+
import type { PostProcessShaderEntry } from '../fullscreen-post-process-pass';
|
|
31
38
|
import {
|
|
32
39
|
buildFullscreenPostProcessPass,
|
|
33
40
|
createFullscreenBindGroup,
|
|
34
41
|
isTemporalFullscreenBinding,
|
|
42
|
+
postProcessShaderEntrySignature,
|
|
43
|
+
postProcessShaderModuleLabel,
|
|
35
44
|
} from '../fullscreen-post-process-pass';
|
|
36
45
|
import type { PreparedGpuDrivenFrame } from '../gpu-driven/production-raster';
|
|
37
46
|
import {
|
|
@@ -40,6 +49,10 @@ import {
|
|
|
40
49
|
GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
|
|
41
50
|
GPU_TEXTURE_USAGE_TEXTURE_BINDING,
|
|
42
51
|
} from '../gpu-texture-usage';
|
|
52
|
+
import {
|
|
53
|
+
type StandardTopologyInputValue,
|
|
54
|
+
standardLightingTopologySignature,
|
|
55
|
+
} from '../pipeline/standard-lighting/topology';
|
|
43
56
|
import { resolveVolumetricFogProfile, STANDARD_PIPELINE_ID } from '../pipeline/standard-profile';
|
|
44
57
|
import type { CameraSnapshot } from '../render-contract';
|
|
45
58
|
import type {
|
|
@@ -48,6 +61,9 @@ import type {
|
|
|
48
61
|
RenderPipelineTopology,
|
|
49
62
|
} from '../render-pipeline';
|
|
50
63
|
import type { ExtractedLights, ExtractedVolumetricFog } from '../render-system-extract';
|
|
64
|
+
import { SHADOW_ATLAS_DEFAULT_FACE_SIZE, SHADOW_ATLAS_DEFAULT_LAYERS } from '../shadow-atlas';
|
|
65
|
+
import type { RenderTarget } from '../targets/contracts';
|
|
66
|
+
import type { RenderTargetPhysical } from '../targets/physical';
|
|
51
67
|
import {
|
|
52
68
|
abortTemporalGpuSubmit,
|
|
53
69
|
commitTemporalGpuSubmit,
|
|
@@ -64,8 +80,15 @@ import { hasVolumetricFogCapability } from '../volume/capability';
|
|
|
64
80
|
import { deriveVolumetricFogExtent, deriveVolumetricFogResolvedExtent } from '../volume/resources';
|
|
65
81
|
import { buildPerFrameBindGroups } from './frame-lighting';
|
|
66
82
|
import { getTextureIdentity, type RenderFrameState } from './frame-snapshot';
|
|
67
|
-
import type {
|
|
68
|
-
import type {
|
|
83
|
+
import type { GpuPassTimingPassIdentity } from './gpu-pass-timing/contract.js';
|
|
84
|
+
import type { GpuPassTimingCapture, GpuPassTimingSession } from './gpu-pass-timing/session.js';
|
|
85
|
+
import type { GpuTimingCapture, VolumeTimingTimestampWrites } from './gpu-timing';
|
|
86
|
+
import { encodeMainPass } from './main-pass';
|
|
87
|
+
import type {
|
|
88
|
+
_InternalRenderPipelineContext,
|
|
89
|
+
PipelineState,
|
|
90
|
+
RenderSystemInternals,
|
|
91
|
+
} from './render-context';
|
|
69
92
|
import { resolveSurfaceFormatPair, resolveSurfaceProfile } from './render-context';
|
|
70
93
|
|
|
71
94
|
export interface TemporalGraphCapabilities {
|
|
@@ -206,6 +229,465 @@ export function createTemporalGraphRoster(input: {
|
|
|
206
229
|
};
|
|
207
230
|
}
|
|
208
231
|
|
|
232
|
+
export interface CubeCaptureGraphWork {
|
|
233
|
+
readonly target: RenderTarget;
|
|
234
|
+
readonly faceIndex: number;
|
|
235
|
+
readonly physical: RenderTargetPhysical;
|
|
236
|
+
readonly faceCamera: import('../render-contract').CameraSnapshot;
|
|
237
|
+
readonly viewBindGroupDynamicOffset: number;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export interface CubeCaptureGraphState {
|
|
241
|
+
work: readonly CubeCaptureGraphWork[];
|
|
242
|
+
reflectionProbes?: ReflectionProbeGraphState;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface ReflectionProbeFilterGraphWork {
|
|
246
|
+
readonly probeIndex: number;
|
|
247
|
+
readonly faceIndex: number;
|
|
248
|
+
readonly mipLevel: number;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export interface ReflectionProbeFilterGraphState {
|
|
252
|
+
readonly work: readonly ReflectionProbeFilterGraphWork[];
|
|
253
|
+
readonly maxStepsPerFrame: number;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export interface ReflectionProbeGraphWork {
|
|
257
|
+
readonly probeIndex: number;
|
|
258
|
+
readonly rawTexture: Texture;
|
|
259
|
+
readonly rawCubeView: TextureView;
|
|
260
|
+
readonly rawFaceViews: readonly TextureView[];
|
|
261
|
+
readonly rawDepthTexture: Texture;
|
|
262
|
+
readonly rawCaptureFace: number | undefined;
|
|
263
|
+
readonly rawDepthView: TextureView;
|
|
264
|
+
readonly rawSize: number;
|
|
265
|
+
readonly faceCamera?: import('../render-contract').CameraSnapshot;
|
|
266
|
+
readonly viewBindGroupDynamicOffset?: number;
|
|
267
|
+
readonly filteredTexture: Texture;
|
|
268
|
+
readonly filteredCubeView: TextureView;
|
|
269
|
+
readonly filteredFaceViewsByMip: readonly (readonly TextureView[])[];
|
|
270
|
+
readonly outputFormat: TextureFormat;
|
|
271
|
+
readonly sampler: Sampler;
|
|
272
|
+
readonly filterPipeline: RenderPipeline;
|
|
273
|
+
readonly filterGroup0: BindGroup | undefined;
|
|
274
|
+
readonly filterGroup1: BindGroup;
|
|
275
|
+
readonly cubeVertexBuffer: Buffer;
|
|
276
|
+
readonly filteredSize: number;
|
|
277
|
+
readonly step: ReflectionProbeFilterGraphWork | undefined;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export interface ReflectionProbeGraphState {
|
|
281
|
+
readonly work: readonly ReflectionProbeGraphWork[];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function boundedReflectionProbeFilterWork(
|
|
285
|
+
state: ReflectionProbeFilterGraphState,
|
|
286
|
+
): readonly ReflectionProbeFilterGraphWork[] {
|
|
287
|
+
return state.work.slice(0, Math.max(0, state.maxStepsPerFrame));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function renderTargetMipCount(work: CubeCaptureGraphWork): number {
|
|
291
|
+
const { descriptor } = work.physical;
|
|
292
|
+
return descriptor.mipLevels === 1
|
|
293
|
+
? 1
|
|
294
|
+
: Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function addCubeCaptureGraphPasses(
|
|
298
|
+
builder: RenderGraphBuilder<RenderPipelineFrame>,
|
|
299
|
+
state: CubeCaptureGraphState,
|
|
300
|
+
): Result<void, RenderGraphError> {
|
|
301
|
+
for (let index = 0; index < state.work.length; index += 1) {
|
|
302
|
+
const slot = index;
|
|
303
|
+
const initial = state.work[slot];
|
|
304
|
+
if (initial === undefined) continue;
|
|
305
|
+
const current = (): CubeCaptureGraphWork => state.work[slot] ?? initial;
|
|
306
|
+
const texture = builder.importTexture(
|
|
307
|
+
`cube-capture.${slot}.texture`,
|
|
308
|
+
{
|
|
309
|
+
format: initial.physical.descriptor.format,
|
|
310
|
+
size: {
|
|
311
|
+
width: initial.physical.descriptor.width,
|
|
312
|
+
height: initial.physical.descriptor.height,
|
|
313
|
+
depthOrArrayLayers: initial.physical.descriptor.sampleCount === 4 ? 1 : 6,
|
|
314
|
+
},
|
|
315
|
+
mipLevelCount:
|
|
316
|
+
initial.physical.descriptor.sampleCount === 4 ? 1 : renderTargetMipCount(initial),
|
|
317
|
+
sampleCount: initial.physical.descriptor.sampleCount,
|
|
318
|
+
dimension: '2d',
|
|
319
|
+
usage: 0x10 | 0x04 | 0x01,
|
|
320
|
+
},
|
|
321
|
+
() => current().physical.colorTextures[current().faceIndex] ?? initial.physical.texture,
|
|
322
|
+
);
|
|
323
|
+
if (!texture.ok) return texture;
|
|
324
|
+
const color = builder.importView(
|
|
325
|
+
texture.value,
|
|
326
|
+
{
|
|
327
|
+
label: `cube-capture.${slot}.color`,
|
|
328
|
+
dimension: '2d',
|
|
329
|
+
baseMipLevel: 0,
|
|
330
|
+
mipLevelCount: 1,
|
|
331
|
+
baseArrayLayer: initial.physical.descriptor.sampleCount === 4 ? 0 : initial.faceIndex,
|
|
332
|
+
arrayLayerCount: 1,
|
|
333
|
+
},
|
|
334
|
+
() =>
|
|
335
|
+
current().physical.faceViews[current().faceIndex] ??
|
|
336
|
+
initial.physical.faceViews[initial.faceIndex] ??
|
|
337
|
+
initial.physical.view,
|
|
338
|
+
);
|
|
339
|
+
if (!color.ok) return color;
|
|
340
|
+
const depthTexture = builder.importTexture(
|
|
341
|
+
`cube-capture.${slot}.depth-texture`,
|
|
342
|
+
{
|
|
343
|
+
format: 'depth24plus-stencil8',
|
|
344
|
+
size: {
|
|
345
|
+
width: initial.physical.descriptor.width,
|
|
346
|
+
height: initial.physical.descriptor.height,
|
|
347
|
+
depthOrArrayLayers: initial.physical.descriptor.sampleCount === 4 ? 1 : 6,
|
|
348
|
+
},
|
|
349
|
+
mipLevelCount: 1,
|
|
350
|
+
sampleCount: initial.physical.descriptor.sampleCount,
|
|
351
|
+
dimension: '2d',
|
|
352
|
+
usage: 0x10,
|
|
353
|
+
},
|
|
354
|
+
() => current().physical.depthTextures[current().faceIndex] as Texture,
|
|
355
|
+
);
|
|
356
|
+
if (!depthTexture.ok) return depthTexture;
|
|
357
|
+
const depth = builder.importView(
|
|
358
|
+
depthTexture.value,
|
|
359
|
+
{
|
|
360
|
+
label: `cube-capture.${slot}.depth`,
|
|
361
|
+
dimension: '2d',
|
|
362
|
+
baseArrayLayer: initial.physical.descriptor.sampleCount === 4 ? 0 : initial.faceIndex,
|
|
363
|
+
arrayLayerCount: 1,
|
|
364
|
+
},
|
|
365
|
+
() => current().physical.depthViews[current().faceIndex] as TextureView,
|
|
366
|
+
);
|
|
367
|
+
if (!depth.ok) return depth;
|
|
368
|
+
const resolveTexture =
|
|
369
|
+
initial.physical.descriptor.sampleCount === 4
|
|
370
|
+
? builder.importTexture(
|
|
371
|
+
`cube-capture.${slot}.resolve-texture`,
|
|
372
|
+
{
|
|
373
|
+
format: initial.physical.descriptor.format,
|
|
374
|
+
size: {
|
|
375
|
+
width: initial.physical.descriptor.width,
|
|
376
|
+
height: initial.physical.descriptor.height,
|
|
377
|
+
depthOrArrayLayers: 6,
|
|
378
|
+
},
|
|
379
|
+
mipLevelCount: renderTargetMipCount(initial),
|
|
380
|
+
sampleCount: 1,
|
|
381
|
+
dimension: '2d',
|
|
382
|
+
usage: 0x10 | 0x04 | 0x01,
|
|
383
|
+
},
|
|
384
|
+
() =>
|
|
385
|
+
current().physical.resolveTexture ??
|
|
386
|
+
initial.physical.resolveTexture ??
|
|
387
|
+
initial.physical.texture,
|
|
388
|
+
)
|
|
389
|
+
: undefined;
|
|
390
|
+
if (resolveTexture !== undefined && !resolveTexture.ok) return resolveTexture;
|
|
391
|
+
const resolve =
|
|
392
|
+
resolveTexture === undefined
|
|
393
|
+
? undefined
|
|
394
|
+
: builder.importView(
|
|
395
|
+
resolveTexture.value,
|
|
396
|
+
{
|
|
397
|
+
label: `cube-capture.${slot}.resolve`,
|
|
398
|
+
dimension: '2d',
|
|
399
|
+
baseMipLevel: 0,
|
|
400
|
+
mipLevelCount: 1,
|
|
401
|
+
baseArrayLayer: initial.faceIndex,
|
|
402
|
+
arrayLayerCount: 1,
|
|
403
|
+
},
|
|
404
|
+
() =>
|
|
405
|
+
current().physical.resolveFaceViews[current().faceIndex] ??
|
|
406
|
+
initial.physical.resolveFaceViews[initial.faceIndex] ??
|
|
407
|
+
initial.physical.resolveView,
|
|
408
|
+
);
|
|
409
|
+
if (resolve !== undefined && !resolve.ok) return resolve;
|
|
410
|
+
const added = builder.addRasterPass(`cube-capture-face.${slot}`, {
|
|
411
|
+
accesses: [
|
|
412
|
+
{ resource: color.value, usage: 'color-attachment' },
|
|
413
|
+
{ resource: depth.value, usage: 'depth-stencil-write' },
|
|
414
|
+
...(resolve === undefined
|
|
415
|
+
? []
|
|
416
|
+
: [{ resource: resolve.value, usage: 'color-attachment' as const }]),
|
|
417
|
+
],
|
|
418
|
+
colorAttachments: [
|
|
419
|
+
{
|
|
420
|
+
view: color.value,
|
|
421
|
+
...(resolve === undefined ? {} : { resolveTarget: resolve.value }),
|
|
422
|
+
loadOp: 'clear',
|
|
423
|
+
storeOp: 'store',
|
|
424
|
+
clearValue: () => {
|
|
425
|
+
return { r: 0, g: 0, b: 0, a: 1 };
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
],
|
|
429
|
+
depthStencilAttachment: {
|
|
430
|
+
view: depth.value,
|
|
431
|
+
depthClearValue: 1,
|
|
432
|
+
depthLoadOp: 'clear',
|
|
433
|
+
depthStoreOp: 'store',
|
|
434
|
+
stencilClearValue: 0,
|
|
435
|
+
stencilLoadOp: 'clear',
|
|
436
|
+
stencilStoreOp: 'store',
|
|
437
|
+
},
|
|
438
|
+
encode: ({ pass, frame, resources }) => {
|
|
439
|
+
const internal = frame as _InternalRenderPipelineContext;
|
|
440
|
+
const captureColor = resources.textureView(color.value);
|
|
441
|
+
if (!captureColor.ok) return;
|
|
442
|
+
const captureDepth = resources.textureView(depth.value);
|
|
443
|
+
if (!captureDepth.ok) return;
|
|
444
|
+
const captureResolve =
|
|
445
|
+
resolve === undefined ? undefined : resources.textureView(resolve.value);
|
|
446
|
+
if (resolve !== undefined && (captureResolve === undefined || !captureResolve.ok)) return;
|
|
447
|
+
const captureResolveView = captureResolve?.ok ? captureResolve.value : null;
|
|
448
|
+
const captureContext = {
|
|
449
|
+
...internal,
|
|
450
|
+
gpuDrivenEntityKeys: new Set<number>(),
|
|
451
|
+
camera: current().faceCamera,
|
|
452
|
+
// Cube faces are raw scene captures, not display-camera HDR output.
|
|
453
|
+
// Select the PSO against the actual target attachment so an LDR
|
|
454
|
+
// cube target is rendered by a compatible forward pipeline.
|
|
455
|
+
tonemapActive: false,
|
|
456
|
+
skyboxActive: false,
|
|
457
|
+
transparentColorFormat: initial.physical.descriptor.format as GPUTextureFormat,
|
|
458
|
+
msaaActive: initial.physical.descriptor.sampleCount === 4,
|
|
459
|
+
viewBindGroupDynamicOffset: current().viewBindGroupDynamicOffset,
|
|
460
|
+
geometryColorView: captureColor.value,
|
|
461
|
+
geometryDepthView: captureDepth.value,
|
|
462
|
+
geometryColorResolveView: captureResolveView,
|
|
463
|
+
splitLdrSprite: false,
|
|
464
|
+
ldrSpritePassView: null,
|
|
465
|
+
};
|
|
466
|
+
encodeMainPass(captureContext, pass, undefined, {
|
|
467
|
+
colorViews: [captureColor.value],
|
|
468
|
+
colorFormats: [initial.physical.descriptor.format as GPUTextureFormat],
|
|
469
|
+
depthView: captureDepth.value,
|
|
470
|
+
passKind: 'forward',
|
|
471
|
+
clearColor: [0, 0, 0, 1],
|
|
472
|
+
});
|
|
473
|
+
},
|
|
474
|
+
});
|
|
475
|
+
if (!added.ok) return added;
|
|
476
|
+
}
|
|
477
|
+
return ok(undefined);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export function addReflectionProbeGraphPasses(
|
|
481
|
+
builder: RenderGraphBuilder<RenderPipelineFrame>,
|
|
482
|
+
state: ReflectionProbeGraphState,
|
|
483
|
+
): Result<readonly import('@forgeax/engine-render-graph').GraphAccess[], RenderGraphError> {
|
|
484
|
+
const accesses: import('@forgeax/engine-render-graph').GraphAccess[] = [];
|
|
485
|
+
for (const work of state.work) {
|
|
486
|
+
const raw = builder.importTexture(
|
|
487
|
+
`reflection-probe.${work.probeIndex}.raw`,
|
|
488
|
+
{
|
|
489
|
+
format: work.outputFormat,
|
|
490
|
+
size: { width: work.rawSize, height: work.rawSize, depthOrArrayLayers: 6 },
|
|
491
|
+
mipLevelCount: 1,
|
|
492
|
+
sampleCount: 1,
|
|
493
|
+
dimension: '2d',
|
|
494
|
+
usage: 0x10 | 0x04 | 0x01,
|
|
495
|
+
},
|
|
496
|
+
() => work.rawTexture,
|
|
497
|
+
);
|
|
498
|
+
if (!raw.ok) return raw;
|
|
499
|
+
const rawCube = builder.importView(
|
|
500
|
+
raw.value,
|
|
501
|
+
{
|
|
502
|
+
label: `reflection-probe.${work.probeIndex}.raw-cube`,
|
|
503
|
+
dimension: 'cube',
|
|
504
|
+
arrayLayerCount: 6,
|
|
505
|
+
},
|
|
506
|
+
() => work.rawCubeView,
|
|
507
|
+
);
|
|
508
|
+
if (!rawCube.ok) return rawCube;
|
|
509
|
+
const filtered = builder.importTexture(
|
|
510
|
+
`reflection-probe.${work.probeIndex}.filtered`,
|
|
511
|
+
{
|
|
512
|
+
format: work.outputFormat,
|
|
513
|
+
size: { width: work.filteredSize, height: work.filteredSize, depthOrArrayLayers: 6 },
|
|
514
|
+
mipLevelCount: work.filteredFaceViewsByMip.length,
|
|
515
|
+
sampleCount: 1,
|
|
516
|
+
dimension: '2d',
|
|
517
|
+
usage: 0x10 | 0x04 | 0x01,
|
|
518
|
+
},
|
|
519
|
+
() => work.filteredTexture,
|
|
520
|
+
);
|
|
521
|
+
if (!filtered.ok) return filtered;
|
|
522
|
+
const filteredCube = builder.importView(
|
|
523
|
+
filtered.value,
|
|
524
|
+
{
|
|
525
|
+
label: `reflection-probe.${work.probeIndex}.filtered-cube`,
|
|
526
|
+
dimension: 'cube',
|
|
527
|
+
baseMipLevel: 0,
|
|
528
|
+
mipLevelCount: work.filteredFaceViewsByMip.length,
|
|
529
|
+
arrayLayerCount: 6,
|
|
530
|
+
},
|
|
531
|
+
() => work.filteredCubeView,
|
|
532
|
+
);
|
|
533
|
+
if (!filteredCube.ok) return filteredCube;
|
|
534
|
+
if (work.rawCaptureFace !== undefined) {
|
|
535
|
+
const face = work.rawCaptureFace;
|
|
536
|
+
const view = builder.importView(
|
|
537
|
+
raw.value,
|
|
538
|
+
{
|
|
539
|
+
label: `reflection-probe.${work.probeIndex}.capture-face-${face}`,
|
|
540
|
+
dimension: '2d',
|
|
541
|
+
baseArrayLayer: face,
|
|
542
|
+
arrayLayerCount: 1,
|
|
543
|
+
},
|
|
544
|
+
() => work.rawFaceViews[face] as TextureView,
|
|
545
|
+
);
|
|
546
|
+
if (!view.ok) return view;
|
|
547
|
+
const depthTexture = builder.importTexture(
|
|
548
|
+
`reflection-probe.${work.probeIndex}.capture-depth`,
|
|
549
|
+
{
|
|
550
|
+
format: 'depth24plus-stencil8',
|
|
551
|
+
size: { width: work.rawSize, height: work.rawSize, depthOrArrayLayers: 1 },
|
|
552
|
+
mipLevelCount: 1,
|
|
553
|
+
sampleCount: 1,
|
|
554
|
+
dimension: '2d',
|
|
555
|
+
usage: 0x10,
|
|
556
|
+
},
|
|
557
|
+
() => work.rawDepthTexture,
|
|
558
|
+
);
|
|
559
|
+
if (!depthTexture.ok) return depthTexture;
|
|
560
|
+
const depth = builder.importView(
|
|
561
|
+
depthTexture.value,
|
|
562
|
+
{ label: `reflection-probe.${work.probeIndex}.capture-depth-view`, dimension: '2d' },
|
|
563
|
+
() => work.rawDepthView,
|
|
564
|
+
);
|
|
565
|
+
if (!depth.ok) return depth;
|
|
566
|
+
const added = builder.addRasterPass(`reflection-probe.${work.probeIndex}.capture.${face}`, {
|
|
567
|
+
accesses: [
|
|
568
|
+
{ resource: view.value, usage: 'color-attachment' },
|
|
569
|
+
{ resource: depth.value, usage: 'depth-stencil-write' },
|
|
570
|
+
],
|
|
571
|
+
colorAttachments: [
|
|
572
|
+
{
|
|
573
|
+
view: view.value,
|
|
574
|
+
loadOp: 'clear',
|
|
575
|
+
storeOp: 'store',
|
|
576
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
577
|
+
},
|
|
578
|
+
],
|
|
579
|
+
depthStencilAttachment: {
|
|
580
|
+
view: depth.value,
|
|
581
|
+
depthClearValue: 1,
|
|
582
|
+
depthLoadOp: 'clear',
|
|
583
|
+
depthStoreOp: 'store',
|
|
584
|
+
stencilClearValue: 0,
|
|
585
|
+
stencilLoadOp: 'clear',
|
|
586
|
+
stencilStoreOp: 'store',
|
|
587
|
+
},
|
|
588
|
+
encode: ({ pass, frame, resources }) => {
|
|
589
|
+
const internal = frame as _InternalRenderPipelineContext;
|
|
590
|
+
const captureColor = resources.textureView(view.value);
|
|
591
|
+
const captureDepth = resources.textureView(depth.value);
|
|
592
|
+
if (!captureColor.ok || !captureDepth.ok) return;
|
|
593
|
+
if (work.faceCamera === undefined || work.viewBindGroupDynamicOffset === undefined)
|
|
594
|
+
return;
|
|
595
|
+
encodeMainPass(
|
|
596
|
+
{
|
|
597
|
+
...internal,
|
|
598
|
+
camera: work.faceCamera,
|
|
599
|
+
viewBindGroupDynamicOffset: work.viewBindGroupDynamicOffset,
|
|
600
|
+
geometryColorView: captureColor.value,
|
|
601
|
+
geometryDepthView: captureDepth.value,
|
|
602
|
+
geometryColorResolveView: null,
|
|
603
|
+
transparentColorFormat: work.outputFormat as GPUTextureFormat,
|
|
604
|
+
msaaActive: false,
|
|
605
|
+
splitLdrSprite: false,
|
|
606
|
+
ldrSpritePassView: null,
|
|
607
|
+
},
|
|
608
|
+
pass,
|
|
609
|
+
undefined,
|
|
610
|
+
{
|
|
611
|
+
colorViews: [captureColor.value],
|
|
612
|
+
colorFormats: [work.outputFormat as GPUTextureFormat],
|
|
613
|
+
depthView: captureDepth.value,
|
|
614
|
+
passKind: 'forward',
|
|
615
|
+
clearColor: [0, 0, 0, 1],
|
|
616
|
+
},
|
|
617
|
+
);
|
|
618
|
+
},
|
|
619
|
+
});
|
|
620
|
+
if (!added.ok) return added;
|
|
621
|
+
}
|
|
622
|
+
const step = work.step;
|
|
623
|
+
if (step !== undefined) {
|
|
624
|
+
const mipViews = work.filteredFaceViewsByMip[step.mipLevel];
|
|
625
|
+
const outputView = mipViews?.[step.faceIndex];
|
|
626
|
+
if (outputView === undefined) {
|
|
627
|
+
return err(
|
|
628
|
+
new RenderGraphError({
|
|
629
|
+
code: 'resource-resolution-failed',
|
|
630
|
+
expected: 'every scheduled probe mip has a filtered face view',
|
|
631
|
+
hint: 'rebuild the renderer-owned probe output before compiling the Standard graph',
|
|
632
|
+
detail: {
|
|
633
|
+
resourceLabel: `reflection-probe.${work.probeIndex}.filtered`,
|
|
634
|
+
passName: 'pmrem',
|
|
635
|
+
},
|
|
636
|
+
}),
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
const output = builder.importView(
|
|
640
|
+
filtered.value,
|
|
641
|
+
{
|
|
642
|
+
label: `reflection-probe.${work.probeIndex}.filtered-mip${step.mipLevel}-face${step.faceIndex}`,
|
|
643
|
+
dimension: '2d',
|
|
644
|
+
baseMipLevel: step.mipLevel,
|
|
645
|
+
mipLevelCount: 1,
|
|
646
|
+
baseArrayLayer: step.faceIndex,
|
|
647
|
+
arrayLayerCount: 1,
|
|
648
|
+
},
|
|
649
|
+
() => outputView,
|
|
650
|
+
);
|
|
651
|
+
if (!output.ok) return output;
|
|
652
|
+
const added = builder.addRasterPass(
|
|
653
|
+
`reflection-probe.${work.probeIndex}.pmrem.${step.mipLevel}.${step.faceIndex}`,
|
|
654
|
+
{
|
|
655
|
+
accesses: [
|
|
656
|
+
{ resource: rawCube.value, usage: 'sampled-read' },
|
|
657
|
+
{ resource: output.value, usage: 'color-attachment' },
|
|
658
|
+
],
|
|
659
|
+
colorAttachments: [
|
|
660
|
+
{
|
|
661
|
+
view: output.value,
|
|
662
|
+
loadOp: 'clear',
|
|
663
|
+
storeOp: 'store',
|
|
664
|
+
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
665
|
+
},
|
|
666
|
+
],
|
|
667
|
+
encode: ({ pass }) => {
|
|
668
|
+
if (work.filterGroup0 === undefined) return;
|
|
669
|
+
pass.setPipeline(work.filterPipeline);
|
|
670
|
+
pass.setBindGroup(0, work.filterGroup0);
|
|
671
|
+
pass.setBindGroup(1, work.filterGroup1);
|
|
672
|
+
pass.setVertexBuffer(0, work.cubeVertexBuffer);
|
|
673
|
+
pass.draw(6, 1, step.faceIndex * 6, 0);
|
|
674
|
+
},
|
|
675
|
+
},
|
|
676
|
+
);
|
|
677
|
+
if (!added.ok) return added;
|
|
678
|
+
}
|
|
679
|
+
accesses.push({ resource: filteredCube.value, usage: 'sampled-read' });
|
|
680
|
+
}
|
|
681
|
+
return ok(accesses);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
export {
|
|
685
|
+
projectRenderTargetGraph,
|
|
686
|
+
type RenderTargetGraphInput,
|
|
687
|
+
type RenderTargetGraphProjection,
|
|
688
|
+
type RenderTargetGraphSubresource,
|
|
689
|
+
} from '../targets/graph-projection';
|
|
690
|
+
|
|
209
691
|
export interface RenderFeatureGraphRuntimeState {
|
|
210
692
|
plans: readonly RenderFeaturePlannedFrame[];
|
|
211
693
|
fullscreenEffects: ReadonlyMap<
|
|
@@ -230,10 +712,34 @@ export interface RenderFeatureGraphCandidate {
|
|
|
230
712
|
readonly preparedResourceKey?: string;
|
|
231
713
|
/** Release candidate-owned prepared resources when graph promotion fails. */
|
|
232
714
|
readonly onRejected?: () => void;
|
|
715
|
+
/** Publish candidate-owned runtime declarations only after graph promotion. */
|
|
716
|
+
readonly onAccepted?: () => void;
|
|
717
|
+
/** Discard candidate-only resources when a base graph is kept as fallback. */
|
|
718
|
+
readonly onAbandoned?: () => void;
|
|
233
719
|
}
|
|
234
720
|
|
|
235
721
|
const featureGraphStates = new WeakMap<RenderSystemInternals, RenderFeatureGraphRuntimeState>();
|
|
236
722
|
|
|
723
|
+
interface TimingInstrumentationState {
|
|
724
|
+
readonly instrumentation: RenderGraphPassInstrumentation<RenderPipelineFrame>;
|
|
725
|
+
setCapture(capture: GpuPassTimingCapture | undefined): void;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
const timingInstrumentationStates = new WeakMap<
|
|
729
|
+
RenderSystemInternals,
|
|
730
|
+
TimingInstrumentationState
|
|
731
|
+
>();
|
|
732
|
+
|
|
733
|
+
interface VolumeTimingInstrumentationState {
|
|
734
|
+
readonly instrumentation: RenderGraphPassInstrumentation<RenderPipelineFrame>;
|
|
735
|
+
setCapture(capture: GpuTimingCapture | undefined): void;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
const volumeTimingInstrumentationStates = new WeakMap<
|
|
739
|
+
RenderSystemInternals,
|
|
740
|
+
VolumeTimingInstrumentationState
|
|
741
|
+
>();
|
|
742
|
+
|
|
237
743
|
type CompiledGraphTargetAccess = CompiledRenderGraph<RenderPipelineFrame> & {
|
|
238
744
|
readonly getColorTargetDescriptor: (
|
|
239
745
|
name: string,
|
|
@@ -284,6 +790,31 @@ export function renderFeatureGraphPlanSignature(
|
|
|
284
790
|
);
|
|
285
791
|
}
|
|
286
792
|
|
|
793
|
+
/**
|
|
794
|
+
* Admit fullscreen post-processes as one chain, never as independent passes.
|
|
795
|
+
* A pass whose shader module is still compiling cannot clear a graph target and
|
|
796
|
+
* leave the remainder of the chain sampling an undefined intermediate. The
|
|
797
|
+
* renderer therefore keeps the base output-transform graph until every
|
|
798
|
+
* requested effect is ready, then admits the complete ordered chain together.
|
|
799
|
+
*/
|
|
800
|
+
export function resolvePostProcessChainAdmission(
|
|
801
|
+
effects: readonly string[],
|
|
802
|
+
isReady: (identity: string) => boolean,
|
|
803
|
+
): { readonly admitted: readonly string[]; readonly pending: boolean } {
|
|
804
|
+
// Probe every declaration even after the first miss. A single frame may
|
|
805
|
+
// introduce several effects; evaluating all of them lets the shared cache
|
|
806
|
+
// start every independent compile together instead of serialising warmup on
|
|
807
|
+
// array order.
|
|
808
|
+
let ready = true;
|
|
809
|
+
for (const identity of effects) {
|
|
810
|
+
if (!isReady(identity)) ready = false;
|
|
811
|
+
}
|
|
812
|
+
return {
|
|
813
|
+
admitted: ready ? effects : [],
|
|
814
|
+
pending: !ready,
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
|
|
287
818
|
function validateRenderFeaturePlans(
|
|
288
819
|
plans: readonly RenderFeaturePlannedFrame[],
|
|
289
820
|
): Result<readonly RenderFeaturePlanExecution[], RenderError> {
|
|
@@ -314,6 +845,10 @@ function commitFeatureCandidate(
|
|
|
314
845
|
internals: RenderSystemInternals,
|
|
315
846
|
candidate: RenderFeatureGraphCandidate,
|
|
316
847
|
): void {
|
|
848
|
+
// Publish renderer-owned declarations only after their device resources have
|
|
849
|
+
// been admitted. If the acceptance hook throws, the previously accepted
|
|
850
|
+
// graph/state pair remains visible to the caller.
|
|
851
|
+
candidate.onAccepted?.();
|
|
317
852
|
const state = getRenderFeatureGraphState(internals);
|
|
318
853
|
state.plans = candidate.plans;
|
|
319
854
|
state.fullscreenEffects = candidate.fullscreenEffects;
|
|
@@ -331,8 +866,10 @@ function topologyOf(
|
|
|
331
866
|
shadowMapSize: number | undefined,
|
|
332
867
|
gpuDriven: PreparedGpuDrivenFrame | undefined,
|
|
333
868
|
featureGraphCandidate: RenderFeatureGraphCandidate | undefined,
|
|
869
|
+
cubeCaptureState: CubeCaptureGraphState | undefined,
|
|
334
870
|
transmissionDemand: TransmissionDemand | undefined,
|
|
335
871
|
volumetricFog: ExtractedVolumetricFog | undefined,
|
|
872
|
+
standardLighting: StandardTopologyInputValue | undefined,
|
|
336
873
|
): Result<RenderPipelineTopology, RhiError> {
|
|
337
874
|
const cascadeCount = Math.max(1, Math.min(4, Math.round(lights.cascadeCount ?? 1))) as
|
|
338
875
|
| 1
|
|
@@ -357,6 +894,10 @@ function topologyOf(
|
|
|
357
894
|
...(featureGraphCandidate?.fullscreenEffects ??
|
|
358
895
|
getRenderFeatureGraphState(internals).fullscreenEffects),
|
|
359
896
|
].map(([id]) => id);
|
|
897
|
+
const featurePostEffectDeclarations = [
|
|
898
|
+
...(featureGraphCandidate?.fullscreenEffects ??
|
|
899
|
+
getRenderFeatureGraphState(internals).fullscreenEffects),
|
|
900
|
+
].map(([id, entry]) => [id, postProcessShaderEntrySignature(entry)] as const);
|
|
360
901
|
const config =
|
|
361
902
|
featurePostEffects.length === 0
|
|
362
903
|
? frameState.installedPipelineConfig
|
|
@@ -406,10 +947,13 @@ function topologyOf(
|
|
|
406
947
|
motionBlur: isMotionBlurTemporalDemand(camera.motionBlur),
|
|
407
948
|
},
|
|
408
949
|
shadow: {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
950
|
+
directional:
|
|
951
|
+
shadowMapSize === undefined || lights.cascadeCount === undefined
|
|
952
|
+
? 'disabled'
|
|
953
|
+
: { mapSize: shadowMapSize, cascadeCount },
|
|
954
|
+
spotMapSize: shadowMapSize ?? 1024,
|
|
955
|
+
pointCount: Math.min(SHADOW_ATLAS_DEFAULT_LAYERS, lights.pointShadow.length),
|
|
956
|
+
pointFaceSize: lights.pointShadow[0]?.mapSize ?? SHADOW_ATLAS_DEFAULT_FACE_SIZE,
|
|
413
957
|
spotCount: Math.min(
|
|
414
958
|
4,
|
|
415
959
|
lights.spot.filter(
|
|
@@ -468,10 +1012,12 @@ function topologyOf(
|
|
|
468
1012
|
plans: renderFeatureGraphPlanSignature(
|
|
469
1013
|
featureGraphCandidate?.plans ?? getRenderFeatureGraphState(internals).plans,
|
|
470
1014
|
),
|
|
471
|
-
fullscreenEffects:
|
|
1015
|
+
fullscreenEffects: featurePostEffectDeclarations,
|
|
472
1016
|
preparedResourceKey: featureGraphCandidate?.preparedResourceKey ?? '',
|
|
1017
|
+
cubeCaptureSlots: cubeCaptureState?.work.length ?? 0,
|
|
473
1018
|
}),
|
|
474
1019
|
gpuDrivenTopologySignature: gpuDriven?.topologySignature ?? '',
|
|
1020
|
+
standardLightingTopologySignature: standardLightingTopologySignature(standardLighting),
|
|
475
1021
|
transmissionDemand: transmissionDemand ?? {
|
|
476
1022
|
activeCount: 0,
|
|
477
1023
|
needsRoughMips: false,
|
|
@@ -527,14 +1073,17 @@ function targetResolver(
|
|
|
527
1073
|
};
|
|
528
1074
|
}
|
|
529
1075
|
|
|
530
|
-
function resolveTargetBindings(
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
readonly
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
1076
|
+
function resolveTargetBindings(
|
|
1077
|
+
input: {
|
|
1078
|
+
readonly frame: RenderPipelineFrame;
|
|
1079
|
+
readonly binding: import('../prepare/prepared-graphics-resolver').PreparedGraphicsResolvedResource & {
|
|
1080
|
+
readonly kind: 'bindings';
|
|
1081
|
+
};
|
|
1082
|
+
readonly resources: GraphResourceResolver;
|
|
1083
|
+
readonly resolveTarget: RenderFeatureGraphTargetResolver;
|
|
1084
|
+
},
|
|
1085
|
+
featurePostProcessEntries?: ReadonlyMap<string, PostProcessShaderEntry>,
|
|
1086
|
+
): RenderFeatureGraphBindingsResolution | undefined {
|
|
538
1087
|
const frame = input.frame as import('./render-context')._InternalRenderPipelineContext;
|
|
539
1088
|
const descriptor = input.binding.descriptor;
|
|
540
1089
|
const pipeline = input.binding.pipeline as
|
|
@@ -546,7 +1095,8 @@ function resolveTargetBindings(input: {
|
|
|
546
1095
|
if (descriptor?.values.fullscreen === true && isTemporalFullscreenBinding(descriptor.values)) {
|
|
547
1096
|
const shader = descriptor.values.shader;
|
|
548
1097
|
if (typeof shader !== 'string') return undefined;
|
|
549
|
-
const entry =
|
|
1098
|
+
const entry =
|
|
1099
|
+
featurePostProcessEntries?.get(shader) ?? frame.runtime.lookupPostProcess?.(shader);
|
|
550
1100
|
if (entry === undefined) return undefined;
|
|
551
1101
|
const fullscreen = buildFullscreenPostProcessPass(
|
|
552
1102
|
{ device: frame.runtime.device, errorRegistry: frame.runtime.errorRegistry },
|
|
@@ -636,8 +1186,10 @@ function resolveTargetBindings(input: {
|
|
|
636
1186
|
directionalShadow: frame.frameState.currentDirectionalShadowView ?? undefined,
|
|
637
1187
|
spotShadow: frame.frameState.currentSpotShadowView ?? undefined,
|
|
638
1188
|
},
|
|
1189
|
+
true,
|
|
1190
|
+
frame.standardLighting,
|
|
639
1191
|
).viewBindGroup;
|
|
640
|
-
return viewBindGroup === null ? undefined : { handle: viewBindGroup, dynamicOffsets: [0] };
|
|
1192
|
+
return viewBindGroup === null ? undefined : { handle: viewBindGroup, dynamicOffsets: [0, 0] };
|
|
641
1193
|
}
|
|
642
1194
|
const target = input.resolveTarget(sceneDepth);
|
|
643
1195
|
if (target === undefined) return undefined;
|
|
@@ -707,11 +1259,19 @@ export function ensureCompiledFrameGraph(
|
|
|
707
1259
|
shadowMapSize: number | undefined,
|
|
708
1260
|
gpuDriven?: PreparedGpuDrivenFrame,
|
|
709
1261
|
featureGraphCandidate?: RenderFeatureGraphCandidate,
|
|
1262
|
+
cubeCaptureState?: CubeCaptureGraphState,
|
|
710
1263
|
clearOnly = false,
|
|
711
1264
|
transmissionDemand?: TransmissionDemand,
|
|
712
1265
|
volumetricFog?: ExtractedVolumetricFog,
|
|
713
1266
|
volumeTopologyCandidate = false,
|
|
1267
|
+
standardLighting?: StandardTopologyInputValue,
|
|
714
1268
|
): CompiledRenderGraph<RenderPipelineFrame> | null {
|
|
1269
|
+
const requestedStandardLightingSignature = standardLightingTopologySignature(standardLighting);
|
|
1270
|
+
const lastKnownGood = (): CompiledRenderGraph<RenderPipelineFrame> | null =>
|
|
1271
|
+
frameState.compiledFrameGraph !== null &&
|
|
1272
|
+
frameState.standardLightingGraphSignature === requestedStandardLightingSignature
|
|
1273
|
+
? frameState.compiledFrameGraph
|
|
1274
|
+
: null;
|
|
715
1275
|
const surfaceWidth = Math.max(1, width);
|
|
716
1276
|
const surfaceHeight = Math.max(1, height);
|
|
717
1277
|
const featurePlans = featureGraphCandidate?.plans ?? getRenderFeatureGraphState(internals).plans;
|
|
@@ -719,7 +1279,7 @@ export function ensureCompiledFrameGraph(
|
|
|
719
1279
|
if (!projectedFeaturePlans.ok) {
|
|
720
1280
|
reportRenderFeatureGraphError(internals, projectedFeaturePlans.error);
|
|
721
1281
|
featureGraphCandidate?.onRejected?.();
|
|
722
|
-
return volumeTopologyCandidate ? null :
|
|
1282
|
+
return volumeTopologyCandidate ? null : lastKnownGood();
|
|
723
1283
|
}
|
|
724
1284
|
const topologyResult = topologyOf(
|
|
725
1285
|
internals,
|
|
@@ -733,19 +1293,81 @@ export function ensureCompiledFrameGraph(
|
|
|
733
1293
|
shadowMapSize,
|
|
734
1294
|
gpuDriven,
|
|
735
1295
|
featureGraphCandidate,
|
|
1296
|
+
cubeCaptureState,
|
|
736
1297
|
transmissionDemand,
|
|
737
1298
|
volumetricFog,
|
|
1299
|
+
standardLighting,
|
|
738
1300
|
);
|
|
739
1301
|
if (!topologyResult.ok) {
|
|
740
1302
|
internals.errorRegistry.fire(topologyResult.error);
|
|
741
1303
|
featureGraphCandidate?.onRejected?.();
|
|
742
|
-
return volumeTopologyCandidate ? null :
|
|
1304
|
+
return volumeTopologyCandidate ? null : lastKnownGood();
|
|
1305
|
+
}
|
|
1306
|
+
const requestedPostEffects = topologyResult.value.config?.postEffects ?? [];
|
|
1307
|
+
const featurePostProcessEntries =
|
|
1308
|
+
featureGraphCandidate?.fullscreenEffects ??
|
|
1309
|
+
getRenderFeatureGraphState(internals).fullscreenEffects;
|
|
1310
|
+
const postProcessAdmission = resolvePostProcessChainAdmission(
|
|
1311
|
+
requestedPostEffects,
|
|
1312
|
+
(identity) => {
|
|
1313
|
+
const entry =
|
|
1314
|
+
featurePostProcessEntries.get(identity) ?? internals.lookupPostProcess?.(identity);
|
|
1315
|
+
// Preserve the existing missing-entry failure contract. The graph will
|
|
1316
|
+
// report post-process-not-found during record instead of silently
|
|
1317
|
+
// removing an authored id from the topology.
|
|
1318
|
+
if (entry === undefined) return true;
|
|
1319
|
+
const buildPipeline = internals.buildPostProcessPipeline;
|
|
1320
|
+
const getPipeline = internals.getPostProcessPipeline;
|
|
1321
|
+
if (buildPipeline === undefined || getPipeline === undefined) return true;
|
|
1322
|
+
const built = buildFullscreenPostProcessPass(
|
|
1323
|
+
{ device: internals.device, errorRegistry: internals.errorRegistry },
|
|
1324
|
+
entry,
|
|
1325
|
+
camera.antialias === 'msaa' && topologyResult.value.lane.multisample,
|
|
1326
|
+
);
|
|
1327
|
+
if (built === null) return false;
|
|
1328
|
+
return (
|
|
1329
|
+
getPipeline(
|
|
1330
|
+
identity,
|
|
1331
|
+
built.bindGroupLayout,
|
|
1332
|
+
topologyResult.value.surface.storageFormat as GPUTextureFormat,
|
|
1333
|
+
entry,
|
|
1334
|
+
) !== null
|
|
1335
|
+
);
|
|
1336
|
+
},
|
|
1337
|
+
);
|
|
1338
|
+
const acceptedLkg = lastKnownGood();
|
|
1339
|
+
if (postProcessAdmission.pending && acceptedLkg !== null) {
|
|
1340
|
+
// Do not publish a candidate whose fullscreen chain is only partially
|
|
1341
|
+
// ready. Keep the accepted graph (including its prior post-effect chain)
|
|
1342
|
+
// and retry the same feature candidate on the next frame.
|
|
1343
|
+
featureGraphCandidate?.onRejected?.();
|
|
1344
|
+
return acceptedLkg;
|
|
743
1345
|
}
|
|
744
|
-
const topology =
|
|
745
|
-
|
|
1346
|
+
const topology = postProcessAdmission.pending
|
|
1347
|
+
? {
|
|
1348
|
+
...topologyResult.value,
|
|
1349
|
+
config: {
|
|
1350
|
+
...(topologyResult.value.config ?? {}),
|
|
1351
|
+
postEffects: [],
|
|
1352
|
+
},
|
|
1353
|
+
}
|
|
1354
|
+
: topologyResult.value;
|
|
1355
|
+
const key = JSON.stringify({
|
|
1356
|
+
topology,
|
|
1357
|
+
cubeCaptureSlots: cubeCaptureState?.work.length ?? 0,
|
|
1358
|
+
reflectionProbeSlots: cubeCaptureState?.reflectionProbes?.work.map((work) => [
|
|
1359
|
+
work.probeIndex,
|
|
1360
|
+
work.rawCaptureFace ?? -1,
|
|
1361
|
+
work.step?.faceIndex ?? -1,
|
|
1362
|
+
work.step?.mipLevel ?? -1,
|
|
1363
|
+
]),
|
|
1364
|
+
});
|
|
746
1365
|
if (frameState.compiledFrameGraph !== null && frameState.compiledFrameGraphTopologyKey === key) {
|
|
747
|
-
|
|
1366
|
+
frameState.standardLightingGraphSignature = requestedStandardLightingSignature;
|
|
1367
|
+
if (featureGraphCandidate !== undefined && !postProcessAdmission.pending) {
|
|
748
1368
|
commitFeatureCandidate(internals, featureGraphCandidate);
|
|
1369
|
+
} else if (featureGraphCandidate !== undefined) {
|
|
1370
|
+
featureGraphCandidate.onAbandoned?.();
|
|
749
1371
|
}
|
|
750
1372
|
// A candidate flag only describes a possible topology replacement. When
|
|
751
1373
|
// the derived key is unchanged there is no replacement to stage: reuse the
|
|
@@ -761,6 +1383,7 @@ export function ensureCompiledFrameGraph(
|
|
|
761
1383
|
const built = frameState.activePipeline.build(
|
|
762
1384
|
{
|
|
763
1385
|
graph: builder,
|
|
1386
|
+
...(standardLighting === undefined ? {} : { standardLighting }),
|
|
764
1387
|
capabilities: { rgba16floatRenderable: internals.device.caps.rgba16floatRenderable },
|
|
765
1388
|
...(taaHistory === undefined ? {} : { taaHistory }),
|
|
766
1389
|
encodeTransmissionMip: ({ pass, resources, source }) => {
|
|
@@ -781,11 +1404,21 @@ export function ensureCompiledFrameGraph(
|
|
|
781
1404
|
const resolveTarget = targetResolver(targets, semanticTargets, namedTargets);
|
|
782
1405
|
const projected = projectPlanExecutions(builder, projectedFeaturePlans.value, {
|
|
783
1406
|
resolveTarget,
|
|
784
|
-
resolveBindings: resolveTargetBindings,
|
|
1407
|
+
resolveBindings: (input) => resolveTargetBindings(input, featurePostProcessEntries),
|
|
785
1408
|
reportError: (error) => reportRenderFeatureGraphError(internals, error),
|
|
786
1409
|
});
|
|
787
1410
|
return projected.ok ? ok(undefined) : projected;
|
|
788
1411
|
},
|
|
1412
|
+
contributeCubeCaptures: () => {
|
|
1413
|
+
const reflectionProbes = addReflectionProbeGraphPasses(
|
|
1414
|
+
builder,
|
|
1415
|
+
cubeCaptureState?.reflectionProbes ?? { work: [] },
|
|
1416
|
+
);
|
|
1417
|
+
if (!reflectionProbes.ok) return reflectionProbes;
|
|
1418
|
+
return cubeCaptureState === undefined
|
|
1419
|
+
? ok(undefined)
|
|
1420
|
+
: addCubeCaptureGraphPasses(builder, cubeCaptureState);
|
|
1421
|
+
},
|
|
789
1422
|
hasFeature: (identity) =>
|
|
790
1423
|
projectedFeaturePlans.value.some((execution) => execution.featureIdentity === identity),
|
|
791
1424
|
},
|
|
@@ -794,7 +1427,7 @@ export function ensureCompiledFrameGraph(
|
|
|
794
1427
|
if (!built.ok) {
|
|
795
1428
|
internals.errorRegistry.fire(built.error);
|
|
796
1429
|
featureGraphCandidate?.onRejected?.();
|
|
797
|
-
return volumeTopologyCandidate ? null :
|
|
1430
|
+
return volumeTopologyCandidate ? null : lastKnownGood();
|
|
798
1431
|
}
|
|
799
1432
|
const compiled = builder.compile({
|
|
800
1433
|
device: internals.device,
|
|
@@ -803,7 +1436,7 @@ export function ensureCompiledFrameGraph(
|
|
|
803
1436
|
if (!compiled.ok) {
|
|
804
1437
|
internals.errorRegistry.fire(compiled.error);
|
|
805
1438
|
featureGraphCandidate?.onRejected?.();
|
|
806
|
-
return
|
|
1439
|
+
return lastKnownGood();
|
|
807
1440
|
}
|
|
808
1441
|
const previous = frameState.compiledFrameGraph;
|
|
809
1442
|
if (volumeTopologyCandidate) {
|
|
@@ -813,6 +1446,8 @@ export function ensureCompiledFrameGraph(
|
|
|
813
1446
|
}
|
|
814
1447
|
frameState.compiledFrameGraph = compiled.value;
|
|
815
1448
|
frameState.compiledFrameGraphTopologyKey = key;
|
|
1449
|
+
frameState.standardLightingGraphSignature = requestedStandardLightingSignature;
|
|
1450
|
+
frameState.compiledFrameGraphGeneration += 1;
|
|
816
1451
|
const compiledTargets = compiled.value as CompiledGraphTargetAccess;
|
|
817
1452
|
frameState.graphGeneration += 1;
|
|
818
1453
|
frameState.perFrameGraph = {
|
|
@@ -822,8 +1457,10 @@ export function ensureCompiledFrameGraph(
|
|
|
822
1457
|
graphGeneration: frameState.graphGeneration,
|
|
823
1458
|
};
|
|
824
1459
|
gpuDriven?._commitResourceReplacement();
|
|
825
|
-
if (featureGraphCandidate !== undefined) {
|
|
1460
|
+
if (featureGraphCandidate !== undefined && !postProcessAdmission.pending) {
|
|
826
1461
|
commitFeatureCandidate(internals, featureGraphCandidate);
|
|
1462
|
+
} else if (featureGraphCandidate !== undefined) {
|
|
1463
|
+
featureGraphCandidate.onAbandoned?.();
|
|
827
1464
|
}
|
|
828
1465
|
if (!volumeTopologyCandidate && previous !== null) retire(frameState, previous);
|
|
829
1466
|
return compiled.value;
|
|
@@ -835,9 +1472,17 @@ export function executeCompiledFrameGraph(
|
|
|
835
1472
|
frame: RenderPipelineFrame,
|
|
836
1473
|
encoder: RhiCommandEncoder,
|
|
837
1474
|
runPass?: import('@forgeax/engine-render-graph').RenderGraphPassRunner,
|
|
1475
|
+
readbackFaces?: readonly number[],
|
|
1476
|
+
onSubmitted?: (completed: Promise<unknown>) => void,
|
|
838
1477
|
timingCapture?: GpuTimingCapture,
|
|
839
1478
|
): boolean {
|
|
840
1479
|
const graph = frameState.compiledFrameGraph;
|
|
1480
|
+
const invalidatePostProcessModule = (id: string): void => {
|
|
1481
|
+
const entry = internals.lookupPostProcess?.(id);
|
|
1482
|
+
if (entry !== undefined) {
|
|
1483
|
+
internals.invalidateShaderModule?.(postProcessShaderModuleLabel(id, entry.source));
|
|
1484
|
+
}
|
|
1485
|
+
};
|
|
841
1486
|
const rejectTemporalFrame = (): void => {
|
|
842
1487
|
if (frameState.temporalFrameInput === undefined) return;
|
|
843
1488
|
frameState.temporalFrameTransaction.commit({ accepted: false });
|
|
@@ -849,28 +1494,47 @@ export function executeCompiledFrameGraph(
|
|
|
849
1494
|
rejectTemporalFrame();
|
|
850
1495
|
return false;
|
|
851
1496
|
}
|
|
852
|
-
const
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1497
|
+
const timingHost = internals as RenderSystemInternals & {
|
|
1498
|
+
gpuPassTimingSession?: GpuPassTimingSession | undefined;
|
|
1499
|
+
gpuPassTimingCapture?: GpuPassTimingCapture | undefined;
|
|
1500
|
+
gpuPassTimingSubmittedWork?: Promise<void> | undefined;
|
|
1501
|
+
gpuPassTimingFrameIdentity?:
|
|
1502
|
+
| import('./gpu-pass-timing/session.js').GpuPassTimingFrameIdentity
|
|
1503
|
+
| undefined;
|
|
1504
|
+
gpuPassTimingBeginReason?:
|
|
1505
|
+
| import('./gpu-pass-timing/errors.js').GpuPassTimingReason
|
|
1506
|
+
| undefined;
|
|
1507
|
+
};
|
|
1508
|
+
timingHost.gpuPassTimingCapture = undefined;
|
|
1509
|
+
timingHost.gpuPassTimingSubmittedWork = undefined;
|
|
1510
|
+
timingHost.gpuPassTimingBeginReason = undefined;
|
|
1511
|
+
const timingIdentity = timingHost.gpuPassTimingFrameIdentity;
|
|
1512
|
+
const passTimingResult =
|
|
1513
|
+
timingIdentity === undefined
|
|
1514
|
+
? undefined
|
|
1515
|
+
: timingHost.gpuPassTimingSession?.beginFrame({
|
|
1516
|
+
...timingIdentity,
|
|
1517
|
+
graphGeneration: frameState.compiledFrameGraphGeneration,
|
|
1518
|
+
});
|
|
1519
|
+
const capture = passTimingResult?.ok === true ? passTimingResult.value : undefined;
|
|
1520
|
+
if (passTimingResult?.ok === false) timingHost.gpuPassTimingBeginReason = passTimingResult.error;
|
|
1521
|
+
const passTimingCapture = capture;
|
|
1522
|
+
timingHost.gpuPassTimingCapture = passTimingCapture;
|
|
1523
|
+
const timingInstrumentationState =
|
|
1524
|
+
passTimingCapture !== undefined
|
|
1525
|
+
? getTimingInstrumentationState(internals, passTimingCapture)
|
|
1526
|
+
: timingCapture === undefined
|
|
1527
|
+
? undefined
|
|
1528
|
+
: getVolumeTimingInstrumentationState(internals, timingCapture);
|
|
867
1529
|
type PreparedCommand = { readonly command: CommandBuffer };
|
|
868
1530
|
let preparedCommand: PreparedCommand = { command: undefined as never };
|
|
869
1531
|
const transaction = executeRendererFrameTransaction<PreparedCommand>({
|
|
870
1532
|
build: () => ({ ok: true, value: { command: undefined as never } }),
|
|
871
1533
|
execute: () => {
|
|
872
|
-
const executed = graph.execute(frame,
|
|
1534
|
+
const executed = graph.execute(frame, runPass, timingInstrumentationState?.instrumentation);
|
|
1535
|
+
timingInstrumentationState?.setCapture(undefined);
|
|
873
1536
|
if (!executed.ok) {
|
|
1537
|
+
passTimingCapture?.abort({ code: executed.error.code });
|
|
874
1538
|
internals.errorRegistry.fire(executed.error);
|
|
875
1539
|
return { ok: false, stage: 'execute' };
|
|
876
1540
|
}
|
|
@@ -1000,6 +1664,7 @@ export function executeCompiledFrameGraph(
|
|
|
1000
1664
|
);
|
|
1001
1665
|
}
|
|
1002
1666
|
}
|
|
1667
|
+
internals.encodeRenderTargetReadbacks?.(encoder, readbackFaces);
|
|
1003
1668
|
const stagedGpuState = frameState.temporalGpuState;
|
|
1004
1669
|
if (stagedGpuState !== undefined && !hasPendingTemporalGpuSubmit(stagedGpuState)) {
|
|
1005
1670
|
internals.errorRegistry.fire(
|
|
@@ -1011,6 +1676,10 @@ export function executeCompiledFrameGraph(
|
|
|
1011
1676
|
);
|
|
1012
1677
|
return { ok: false, stage: 'finish' };
|
|
1013
1678
|
}
|
|
1679
|
+
if (passTimingCapture !== undefined) {
|
|
1680
|
+
const tail = passTimingCapture.encodeTail(encoder);
|
|
1681
|
+
if (!tail.ok) passTimingCapture.abort({ code: tail.error.code });
|
|
1682
|
+
}
|
|
1014
1683
|
const resolved = timingCapture?.resolve(encoder);
|
|
1015
1684
|
if (resolved !== undefined && !resolved.ok) {
|
|
1016
1685
|
timingCapture?.discard();
|
|
@@ -1018,6 +1687,7 @@ export function executeCompiledFrameGraph(
|
|
|
1018
1687
|
}
|
|
1019
1688
|
const finished = encoder.finish();
|
|
1020
1689
|
if (!finished.ok) {
|
|
1690
|
+
passTimingCapture?.abort({ code: finished.error.code });
|
|
1021
1691
|
timingCapture?.discard();
|
|
1022
1692
|
internals.errorRegistry.fire(finished.error);
|
|
1023
1693
|
return { ok: false, stage: 'finish' };
|
|
@@ -1028,6 +1698,7 @@ export function executeCompiledFrameGraph(
|
|
|
1028
1698
|
submit: () => {
|
|
1029
1699
|
const submitted = internals.device.queue.submit([preparedCommand.command]);
|
|
1030
1700
|
if (!submitted.ok) {
|
|
1701
|
+
passTimingCapture?.abort({ code: submitted.error.code });
|
|
1031
1702
|
timingCapture?.discard();
|
|
1032
1703
|
internals.errorRegistry.fire(submitted.error);
|
|
1033
1704
|
return { ok: false, stage: 'submit' };
|
|
@@ -1036,6 +1707,11 @@ export function executeCompiledFrameGraph(
|
|
|
1036
1707
|
return { ok: true, value: undefined };
|
|
1037
1708
|
},
|
|
1038
1709
|
commit: () => {
|
|
1710
|
+
if (passTimingCapture !== undefined) {
|
|
1711
|
+
const completion = internals.device.queue.onSubmittedWorkDone();
|
|
1712
|
+
timingHost.gpuPassTimingSubmittedWork = completion;
|
|
1713
|
+
passTimingCapture.markSubmitted(completion);
|
|
1714
|
+
}
|
|
1039
1715
|
if (frameState.bloomFrameReceipts !== undefined) {
|
|
1040
1716
|
internals
|
|
1041
1717
|
.getPipelineState()
|
|
@@ -1049,7 +1725,7 @@ export function executeCompiledFrameGraph(
|
|
|
1049
1725
|
frameState.activeTemporalGpuState = stagedGpuState;
|
|
1050
1726
|
if (previousGpuState !== undefined && previousGpuState !== stagedGpuState) {
|
|
1051
1727
|
internals.clearPostProcessPipelineCache?.('forgeax.taa-resolve');
|
|
1052
|
-
|
|
1728
|
+
invalidatePostProcessModule('forgeax.taa-resolve');
|
|
1053
1729
|
retireTemporalGpuStateAfterFence(
|
|
1054
1730
|
previousGpuState,
|
|
1055
1731
|
internals.device.queue,
|
|
@@ -1079,7 +1755,7 @@ export function executeCompiledFrameGraph(
|
|
|
1079
1755
|
}
|
|
1080
1756
|
if (stagedTemporalCommit.kind === 'off') {
|
|
1081
1757
|
internals.clearPostProcessPipelineCache?.('forgeax.taa-resolve');
|
|
1082
|
-
|
|
1758
|
+
invalidatePostProcessModule('forgeax.taa-resolve');
|
|
1083
1759
|
const activeGpuState = frameState.activeTemporalGpuState;
|
|
1084
1760
|
if (activeGpuState !== undefined) {
|
|
1085
1761
|
retireTemporalGpuStateAfterFence(
|
|
@@ -1104,8 +1780,12 @@ export function executeCompiledFrameGraph(
|
|
|
1104
1780
|
frameState.environmentLifecycle?.publish(frameState.environmentGeneration);
|
|
1105
1781
|
frameState.environmentGeneration = undefined;
|
|
1106
1782
|
}
|
|
1783
|
+
onSubmitted?.(internals.device.queue.onSubmittedWorkDone());
|
|
1107
1784
|
},
|
|
1108
1785
|
abort: (failure) => {
|
|
1786
|
+
passTimingCapture?.abort({ code: failure.stage });
|
|
1787
|
+
timingHost.gpuPassTimingCapture = undefined;
|
|
1788
|
+
timingHost.gpuPassTimingSubmittedWork = undefined;
|
|
1109
1789
|
timingCapture?.discard();
|
|
1110
1790
|
frameState.bloomFrameReceipts = undefined;
|
|
1111
1791
|
if (frameState.environmentGeneration !== undefined) {
|
|
@@ -1133,3 +1813,172 @@ export function executeCompiledFrameGraph(
|
|
|
1133
1813
|
if (!transaction.ok) rejectTemporalFrame();
|
|
1134
1814
|
return transaction.ok;
|
|
1135
1815
|
}
|
|
1816
|
+
|
|
1817
|
+
function getTimingInstrumentationState(
|
|
1818
|
+
internals: RenderSystemInternals,
|
|
1819
|
+
capture: GpuPassTimingCapture,
|
|
1820
|
+
): TimingInstrumentationState {
|
|
1821
|
+
const existing = timingInstrumentationStates.get(internals);
|
|
1822
|
+
if (existing !== undefined) {
|
|
1823
|
+
existing.setCapture(capture);
|
|
1824
|
+
return existing;
|
|
1825
|
+
}
|
|
1826
|
+
type TimestampWrites = NonNullable<ReturnType<GpuPassTimingCapture['timestampWrites']>>;
|
|
1827
|
+
const activeIdentity: {
|
|
1828
|
+
passName: string;
|
|
1829
|
+
passKind: GpuPassTimingPassIdentity['passKind'];
|
|
1830
|
+
executionIndex: number;
|
|
1831
|
+
} = {
|
|
1832
|
+
passName: '',
|
|
1833
|
+
passKind: 'raster',
|
|
1834
|
+
executionIndex: 0,
|
|
1835
|
+
};
|
|
1836
|
+
let activeWrites: TimestampWrites | undefined;
|
|
1837
|
+
let activeCapture: GpuPassTimingCapture | undefined = capture;
|
|
1838
|
+
const rasterScope: RenderGraphPassInstrumentationScope = {
|
|
1839
|
+
renderPassDescriptor: (descriptor) => {
|
|
1840
|
+
const capture = activeCapture;
|
|
1841
|
+
const identity = activeIdentity;
|
|
1842
|
+
const writes = activeWrites;
|
|
1843
|
+
if (capture === undefined || identity === undefined || writes === undefined) {
|
|
1844
|
+
return descriptor;
|
|
1845
|
+
}
|
|
1846
|
+
if (descriptor.timestampWrites !== undefined) {
|
|
1847
|
+
capture.markOwnerConflict(identity);
|
|
1848
|
+
return descriptor;
|
|
1849
|
+
}
|
|
1850
|
+
(descriptor as { timestampWrites?: TimestampWrites }).timestampWrites = writes;
|
|
1851
|
+
return descriptor;
|
|
1852
|
+
},
|
|
1853
|
+
};
|
|
1854
|
+
const computeScope: RenderGraphPassInstrumentationScope = {
|
|
1855
|
+
computePassDescriptor: (descriptor) => {
|
|
1856
|
+
const capture = activeCapture;
|
|
1857
|
+
const identity = activeIdentity;
|
|
1858
|
+
const writes = activeWrites;
|
|
1859
|
+
if (capture === undefined || identity === undefined || writes === undefined) {
|
|
1860
|
+
return descriptor;
|
|
1861
|
+
}
|
|
1862
|
+
if (descriptor.timestampWrites !== undefined) {
|
|
1863
|
+
capture.markOwnerConflict(identity);
|
|
1864
|
+
return descriptor;
|
|
1865
|
+
}
|
|
1866
|
+
(descriptor as { timestampWrites?: TimestampWrites }).timestampWrites = writes;
|
|
1867
|
+
return descriptor;
|
|
1868
|
+
},
|
|
1869
|
+
};
|
|
1870
|
+
const copyScope: RenderGraphPassInstrumentationScope = {
|
|
1871
|
+
beforeCopy: (encoder) => {
|
|
1872
|
+
const capture = activeCapture;
|
|
1873
|
+
const identity = activeIdentity;
|
|
1874
|
+
if (capture === undefined || identity === undefined) return;
|
|
1875
|
+
capture.copyBoundaryBefore(identity, encoder);
|
|
1876
|
+
},
|
|
1877
|
+
afterCopy: (encoder) => {
|
|
1878
|
+
const capture = activeCapture;
|
|
1879
|
+
const identity = activeIdentity;
|
|
1880
|
+
if (capture === undefined || identity === undefined) return;
|
|
1881
|
+
capture.copyBoundaryAfter(identity, encoder);
|
|
1882
|
+
},
|
|
1883
|
+
};
|
|
1884
|
+
const instrumentation: RenderGraphPassInstrumentation<RenderPipelineFrame> = {
|
|
1885
|
+
begin: (pass) => {
|
|
1886
|
+
const capture = activeCapture;
|
|
1887
|
+
if (capture === undefined) return undefined;
|
|
1888
|
+
activeIdentity.passName = pass.name;
|
|
1889
|
+
activeIdentity.passKind = pass.kind;
|
|
1890
|
+
activeIdentity.executionIndex = pass.executionIndex;
|
|
1891
|
+
activeWrites = capture.recordPass(activeIdentity);
|
|
1892
|
+
if (activeWrites === undefined) return undefined;
|
|
1893
|
+
switch (pass.kind) {
|
|
1894
|
+
case 'raster':
|
|
1895
|
+
return rasterScope;
|
|
1896
|
+
case 'compute':
|
|
1897
|
+
return computeScope;
|
|
1898
|
+
case 'copy':
|
|
1899
|
+
return copyScope;
|
|
1900
|
+
}
|
|
1901
|
+
},
|
|
1902
|
+
};
|
|
1903
|
+
const state: TimingInstrumentationState = {
|
|
1904
|
+
instrumentation,
|
|
1905
|
+
setCapture: (capture) => {
|
|
1906
|
+
activeCapture = capture;
|
|
1907
|
+
if (capture === undefined) {
|
|
1908
|
+
activeWrites = undefined;
|
|
1909
|
+
}
|
|
1910
|
+
},
|
|
1911
|
+
};
|
|
1912
|
+
timingInstrumentationStates.set(internals, state);
|
|
1913
|
+
return state;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
function getVolumeTimingInstrumentationState(
|
|
1917
|
+
internals: RenderSystemInternals,
|
|
1918
|
+
capture: GpuTimingCapture,
|
|
1919
|
+
): VolumeTimingInstrumentationState {
|
|
1920
|
+
const existing = volumeTimingInstrumentationStates.get(internals);
|
|
1921
|
+
if (existing !== undefined) {
|
|
1922
|
+
existing.setCapture(capture);
|
|
1923
|
+
return existing;
|
|
1924
|
+
}
|
|
1925
|
+
let activeCapture: GpuTimingCapture | undefined = capture;
|
|
1926
|
+
let activePassName: string | undefined;
|
|
1927
|
+
let activeWrites: VolumeTimingTimestampWrites | undefined;
|
|
1928
|
+
const rasterScope: RenderGraphPassInstrumentationScope = {
|
|
1929
|
+
renderPassDescriptor: (descriptor) => {
|
|
1930
|
+
const currentCapture = activeCapture;
|
|
1931
|
+
const passName = activePassName;
|
|
1932
|
+
const writes = activeWrites;
|
|
1933
|
+
if (currentCapture === undefined || passName === undefined || writes === undefined) {
|
|
1934
|
+
return descriptor;
|
|
1935
|
+
}
|
|
1936
|
+
if (descriptor.timestampWrites !== undefined) {
|
|
1937
|
+
currentCapture.skipPass(passName);
|
|
1938
|
+
activeWrites = undefined;
|
|
1939
|
+
return descriptor;
|
|
1940
|
+
}
|
|
1941
|
+
return { ...descriptor, timestampWrites: writes };
|
|
1942
|
+
},
|
|
1943
|
+
};
|
|
1944
|
+
const computeScope: RenderGraphPassInstrumentationScope = {
|
|
1945
|
+
computePassDescriptor: (descriptor) => {
|
|
1946
|
+
const currentCapture = activeCapture;
|
|
1947
|
+
const passName = activePassName;
|
|
1948
|
+
const writes = activeWrites;
|
|
1949
|
+
if (currentCapture === undefined || passName === undefined || writes === undefined) {
|
|
1950
|
+
return descriptor;
|
|
1951
|
+
}
|
|
1952
|
+
if (descriptor.timestampWrites !== undefined) {
|
|
1953
|
+
currentCapture.skipPass(passName);
|
|
1954
|
+
activeWrites = undefined;
|
|
1955
|
+
return descriptor;
|
|
1956
|
+
}
|
|
1957
|
+
return { ...descriptor, timestampWrites: writes };
|
|
1958
|
+
},
|
|
1959
|
+
};
|
|
1960
|
+
const instrumentation: RenderGraphPassInstrumentation<RenderPipelineFrame> = {
|
|
1961
|
+
begin: (pass) => {
|
|
1962
|
+
const currentCapture = activeCapture;
|
|
1963
|
+
if (currentCapture === undefined) return undefined;
|
|
1964
|
+
activePassName = pass.name;
|
|
1965
|
+
activeWrites = currentCapture.recordPass(pass.name);
|
|
1966
|
+
if (activeWrites === undefined) return undefined;
|
|
1967
|
+
if (pass.kind === 'raster') return rasterScope;
|
|
1968
|
+
if (pass.kind === 'compute') return computeScope;
|
|
1969
|
+
currentCapture.skipPass(pass.name);
|
|
1970
|
+
activeWrites = undefined;
|
|
1971
|
+
return undefined;
|
|
1972
|
+
},
|
|
1973
|
+
};
|
|
1974
|
+
const state: VolumeTimingInstrumentationState = {
|
|
1975
|
+
instrumentation,
|
|
1976
|
+
setCapture: (nextCapture) => {
|
|
1977
|
+
activeCapture = nextCapture;
|
|
1978
|
+
activePassName = undefined;
|
|
1979
|
+
activeWrites = undefined;
|
|
1980
|
+
},
|
|
1981
|
+
};
|
|
1982
|
+
volumeTimingInstrumentationStates.set(internals, state);
|
|
1983
|
+
return state;
|
|
1984
|
+
}
|