@forgeax/engine-render 0.1.29 → 0.1.31
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 +248 -21
- package/dist/assembly/atmosphere-shader-prewarm.d.ts +1 -1
- package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -1
- package/dist/assembly/device-feature-admission.d.ts +4 -3
- package/dist/assembly/device-feature-admission.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-host.d.ts +6 -0
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +6 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +26 -3
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +24 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -0
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
- package/dist/assembly/recovery/recovery-attempt.d.ts +1 -6
- package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready.d.ts +1 -1
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/capture/scene-projection.d.ts +41 -0
- package/dist/capture/scene-projection.d.ts.map +1 -0
- package/dist/{chunk-BQVQOQJH.mjs → chunk-7MQ3XBSP.mjs} +20 -14
- package/dist/chunk-7MQ3XBSP.mjs.map +1 -0
- package/dist/{chunk-S4DNKQYQ.mjs → chunk-C3DDSXYK.mjs} +86 -33
- package/dist/chunk-C3DDSXYK.mjs.map +1 -0
- package/dist/{chunk-BTWH7BP4.mjs → chunk-FUUO4UND.mjs} +73 -29
- package/dist/chunk-FUUO4UND.mjs.map +1 -0
- package/dist/{chunk-NRNXBLIJ.mjs → chunk-JRBDO2KB.mjs} +46 -6
- package/dist/chunk-JRBDO2KB.mjs.map +1 -0
- package/dist/{chunk-NICXSHAT.mjs → chunk-MDQJPY3T.mjs} +8 -6
- package/dist/chunk-MDQJPY3T.mjs.map +1 -0
- package/dist/{chunk-JQTSEI3Z.mjs → chunk-NO4WZCAH.mjs} +3 -3
- package/dist/chunk-NO4WZCAH.mjs.map +1 -0
- package/dist/{chunk-FUODTTIA.mjs → chunk-PSEQ6QPH.mjs} +621 -108
- package/dist/chunk-PSEQ6QPH.mjs.map +1 -0
- package/dist/{chunk-33XZFTQU.mjs → chunk-S5UE2T5P.mjs} +48 -6
- package/dist/chunk-S5UE2T5P.mjs.map +1 -0
- package/dist/components/directional-light.d.ts +2 -2
- package/dist/components/dynamic-resolution.d.ts +15 -0
- package/dist/components/dynamic-resolution.d.ts.map +1 -0
- package/dist/components/index.d.ts +1 -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 +1 -0
- package/dist/components/reflection-probe.d.ts.map +1 -1
- package/dist/components/skylight.d.ts +4 -1
- package/dist/components/skylight.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +2172 -796
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/device-scope.d.ts +2 -0
- package/dist/device/device-scope.d.ts.map +1 -1
- package/dist/device/gpu-residency.d.ts +2 -2
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/environment/background.d.ts +3 -2
- package/dist/environment/background.d.ts.map +1 -1
- package/dist/environment/ibl.d.ts +11 -0
- package/dist/environment/ibl.d.ts.map +1 -0
- package/dist/environment/storage.d.ts +14 -0
- package/dist/environment/storage.d.ts.map +1 -0
- package/dist/errors/gpu-driven.d.ts +2 -2
- package/dist/errors/gpu-driven.d.ts.map +1 -1
- package/dist/errors/render.d.ts +35 -1
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +7 -0
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +18 -1
- package/dist/extract/gpu-driven.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts +24 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -0
- package/dist/gpu-driven/material-bindings.d.ts +7 -0
- package/dist/gpu-driven/material-bindings.d.ts.map +1 -0
- package/dist/gpu-driven/prepared-draw.d.ts +2 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +27 -6
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-resource.d.ts +5 -2
- package/dist/gpu-resource.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +3 -0
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +2 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +3 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +83 -81
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +7 -5
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +16 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/internal.mjs +6 -6
- package/dist/material-row.d.ts +10 -0
- package/dist/material-row.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +3 -1
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/render-extent.d.ts +51 -0
- package/dist/pipeline/render-extent.d.ts.map +1 -0
- package/dist/pipeline/standard-build-context.d.ts +7 -0
- package/dist/pipeline/standard-build-context.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts +3 -2
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline/standard-profile.d.ts +2 -1
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +3 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/post-process-errors.d.ts +9 -2
- package/dist/post-process-errors.d.ts.map +1 -1
- package/dist/prepare/extended-lighting/resources.d.ts +3 -3
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +3 -8
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +3 -2
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +7 -2
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +6 -3
- package/dist/record/main-pass-material.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/prepared-material-bindings.d.ts.map +1 -1
- package/dist/record/recovery-pipeline.d.ts +9 -1
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +34 -3
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -2
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +5 -2
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/reflection/background.d.ts +14 -0
- package/dist/reflection/background.d.ts.map +1 -0
- package/dist/reflection/filter.d.ts.map +1 -1
- package/dist/reflection/projection.d.ts +1 -0
- package/dist/reflection/projection.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts +4 -2
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +47 -32
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +17 -1
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +9 -2
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +29 -2
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +2 -0
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/ssao-config.d.ts +8 -6
- package/dist/ssao-config.d.ts.map +1 -1
- package/dist/ssr/graph.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- package/dist/temporal/standard-scene-data.d.ts +2 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts +15 -0
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -0
- package/dist/temporal/temporal-view.d.ts +6 -2
- package/dist/temporal/temporal-view.d.ts.map +1 -1
- package/dist/temporal/view.d.ts +6 -0
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +6 -0
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +1 -0
- package/dist/volume/component.d.ts.map +1 -1
- package/package.json +21 -21
- package/src/__tests__/capture-scene-projection.unit.test.ts +24 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +15 -24
- package/src/__tests__/device-loss-fanout.unit.test.ts +43 -0
- package/src/__tests__/dynamic-geometry-batch.unit.test.ts +157 -0
- package/src/__tests__/dynamic-geometry.unit.test.ts +36 -0
- package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +81 -0
- package/src/__tests__/factory-contract.integration.test.ts +164 -1
- package/src/__tests__/frame-observation.contract.test.ts +21 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +1 -1
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +20 -1
- package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +0 -3
- package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +0 -3
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +11 -6
- package/src/__tests__/gpu-driven-production.integration.test.ts +13 -25
- package/src/__tests__/gpu-driven-view.unit.test.ts +1 -0
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +15 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +14 -1
- package/src/__tests__/gpu-resource-scope.unit.test.ts +71 -0
- package/src/__tests__/gpu-scene.unit.test.ts +55 -1
- package/src/__tests__/materials-standard-contract.unit.test.ts +5 -1
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +8 -0
- package/src/__tests__/morph-neutral-admission.unit.test.ts +19 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +6 -1
- package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -5
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +216 -5
- package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +68 -1
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +12 -10
- package/src/__tests__/reflection-probe-box.dawn.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +9 -0
- package/src/__tests__/reflection-probe-orientation.dawn.test.ts +294 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +5 -15
- package/src/__tests__/reflection-probe-updates.unit.test.ts +129 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +3 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +5 -1
- package/src/__tests__/render-extent.unit.test.ts +63 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +3 -2
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +173 -9
- package/src/__tests__/shader-manifest-fixture.ts +6 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +8 -1
- package/src/__tests__/specular-environment-scale.dawn.test.ts +4 -2
- package/src/__tests__/ssao-config.unit.test.ts +7 -0
- package/src/__tests__/ssao-surface.dawn.test.ts +252 -0
- package/src/__tests__/ssr-cube-silhouette.dawn.test.ts +270 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +51 -43
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +4 -0
- package/src/__tests__/ssr-gpu-dispatch.ts +10 -5
- package/src/__tests__/ssr-graph-topology.unit.test.ts +2 -2
- package/src/__tests__/ssr-hiz.browser.test.ts +1 -1
- package/src/__tests__/ssr-hiz.dawn.test.ts +1 -1
- package/src/__tests__/ssr-spatial.integration.test.ts +1 -1
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +40 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +238 -1
- package/src/__tests__/standard-profile-oracle.unit.test.ts +27 -0
- package/src/__tests__/taa-coverage-edge.dawn.test.ts +6 -0
- package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +5 -1
- package/src/__tests__/taa-stability-feedback.ts +1 -0
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +2 -2
- package/src/__tests__/temporal-view.unit.test.ts +17 -0
- package/src/__tests__/transmission-prewarm.unit.test.ts +57 -0
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +62 -13
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +7 -7
- package/src/assembly/atmosphere-shader-prewarm.ts +3 -2
- package/src/assembly/device-feature-admission.ts +9 -4
- package/src/assembly/dynamic-geometry-host.ts +236 -163
- package/src/assembly/host-contract.ts +9 -0
- package/src/assembly/material/assembly.ts +350 -6
- package/src/assembly/material/pipeline-helpers.ts +100 -0
- package/src/assembly/material-shader-policy.ts +39 -18
- package/src/assembly/recovery/device-loss-fanout.ts +5 -0
- package/src/assembly/recovery/recovery-attempt.ts +2 -29
- package/src/assembly/recovery/renderer-recover.ts +6 -9
- package/src/assembly/renderer-facade.ts +22 -1
- package/src/assembly/shader-prewarm-policy.ts +14 -1
- package/src/assembly/webgpu-ready.ts +28 -19
- package/src/assembly/webgpu-renderer.ts +95 -95
- package/src/capture/scene-projection.ts +37 -0
- package/src/components/__tests__/dynamic-resolution-schema.unit.test.ts +65 -0
- package/src/components/__tests__/light-radius.integration.test.ts +59 -0
- package/src/components/directional-light.ts +3 -3
- package/src/components/dynamic-resolution.ts +67 -0
- package/src/components/index.ts +1 -0
- package/src/components/light-helpers.ts +6 -1
- package/src/components/reflection-probe.ts +1 -0
- package/src/components/skylight.ts +4 -1
- package/src/device/device-scope.ts +13 -7
- package/src/device/gpu-residency.ts +11 -11
- package/src/dynamic-geometry.ts +13 -8
- package/src/environment/background.ts +30 -12
- package/src/environment/ibl.ts +211 -0
- package/src/environment/storage.ts +63 -0
- package/src/errors/gpu-driven.ts +10 -3
- package/src/errors/render.ts +64 -0
- package/src/extract/camera.ts +12 -1
- package/src/extract/contracts.ts +10 -0
- package/src/extract/gpu-driven.ts +72 -17
- package/src/gpu-driven/batch-topology.ts +33 -11
- package/src/gpu-driven/material-artifacts.ts +179 -0
- package/src/gpu-driven/material-bindings.ts +41 -0
- package/src/gpu-driven/prepared-draw.ts +13 -2
- package/src/gpu-driven/production-raster.ts +681 -164
- package/src/gpu-resource.ts +21 -2
- package/src/gpu-scene-schema.ts +11 -2
- package/src/gpu-scene.ts +14 -3
- package/src/hdrp-buffers.ts +69 -0
- package/src/ibl/IblPipelineCache.ts +5 -0
- package/src/ibl/skylight-bind-group.ts +27 -17
- package/src/index.ts +92 -81
- package/src/inspection-types.ts +16 -1
- package/src/material-row.ts +60 -11
- package/src/pbr-pipeline.ts +13 -2
- package/src/pipeline/render-extent.ts +111 -0
- package/src/pipeline/standard-build-context.ts +7 -0
- package/src/pipeline/standard-forward-lane.ts +41 -24
- package/src/pipeline/standard-pipeline.ts +47 -18
- package/src/pipeline/standard-post.ts +4 -0
- package/src/pipeline/standard-profile.ts +2 -1
- package/src/pipeline-builder.ts +12 -3
- package/src/plugin.ts +4 -0
- package/src/post-process-errors.ts +26 -18
- package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +2 -2
- package/src/prepare/extended-lighting/resources.ts +3 -3
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +68 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +45 -0
- package/src/record/__tests__/material-slot-plan.unit.test.ts +9 -0
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +47 -1
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +7 -3
- package/src/record/__tests__/temporal-payload.unit.test.ts +2 -0
- package/src/record/frame-lighting.ts +3 -1
- package/src/record/frame-snapshot.ts +13 -11
- package/src/record/frame.ts +150 -74
- package/src/record/main-pass-geometry.ts +60 -9
- package/src/record/main-pass-material.ts +47 -19
- package/src/record/main-pass.ts +63 -4
- package/src/record/prepared-material-bindings.ts +4 -0
- package/src/record/recovery-pipeline.ts +56 -0
- package/src/record/render-context.ts +34 -3
- package/src/record/shadow-pass.ts +187 -50
- package/src/record/typed-frame-graph.ts +60 -3
- package/src/record/view-ubo.ts +1 -1
- package/src/recovery/render-system-candidate.ts +54 -11
- package/src/reflection/background.ts +151 -0
- package/src/reflection/filter.ts +3 -0
- package/src/reflection/projection.ts +16 -6
- package/src/reflection/record-owner.ts +282 -86
- package/src/render-contract.ts +50 -32
- package/src/render-graph-primitives.ts +28 -3
- package/src/render-pipeline.ts +20 -1
- package/src/render-system-extract-tail.ts +23 -3
- package/src/render-system-extract.ts +127 -42
- package/src/render-system.ts +35 -7
- package/src/scene/render-scene.ts +8 -0
- package/src/ssao-config.ts +25 -8
- package/src/ssr/graph.ts +78 -58
- package/src/temporal/gpu.ts +5 -0
- package/src/temporal/standard-scene-data.ts +7 -1
- package/src/temporal/target-coverage-attachment.ts +72 -0
- package/src/temporal/temporal-view.ts +10 -4
- package/src/temporal/view.ts +12 -2
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +24 -9
- package/src/typed-render-graph-primitives.ts +38 -0
- package/src/volume/component.ts +1 -0
- package/src/volume/passes.ts +3 -3
- package/dist/chunk-33XZFTQU.mjs.map +0 -1
- package/dist/chunk-BQVQOQJH.mjs.map +0 -1
- package/dist/chunk-BTWH7BP4.mjs.map +0 -1
- package/dist/chunk-FUODTTIA.mjs.map +0 -1
- package/dist/chunk-JQTSEI3Z.mjs.map +0 -1
- package/dist/chunk-NICXSHAT.mjs.map +0 -1
- package/dist/chunk-NRNXBLIJ.mjs.map +0 -1
- package/dist/chunk-S4DNKQYQ.mjs.map +0 -1
package/src/record/frame.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { collectGpuDrivenMaterialArtifacts } from '../gpu-driven/material-artifacts';
|
|
2
|
+
import { materialBindingKey, projectMaterialBindingClasses } from '../gpu-driven/material-bindings';
|
|
1
3
|
import { uploadMaterialUniforms } from './material-uniforms';
|
|
2
4
|
// @forgeax/engine-runtime - RenderSystem record stage: frame.
|
|
3
5
|
// Extracted from render-system-record.ts (feat-20260704 M3/w17, pure move).
|
|
@@ -43,6 +45,7 @@ import {
|
|
|
43
45
|
GPU_BUFFER_USAGE_VERTEX,
|
|
44
46
|
} from '../gpu-usage';
|
|
45
47
|
import { disposeTransientInstanceBuffers } from '../instance-buffer-cache';
|
|
48
|
+
import { deriveRenderExtent } from '../pipeline/render-extent';
|
|
46
49
|
import { inspectStandardLighting } from '../pipeline/standard-lighting/inspection';
|
|
47
50
|
import { standardLightingTopologySignature } from '../pipeline/standard-lighting/topology';
|
|
48
51
|
import { inspectPointShadow } from '../point-shadow-inspection';
|
|
@@ -401,18 +404,25 @@ export interface MaterialSlotPlan<T extends object> {
|
|
|
401
404
|
*/
|
|
402
405
|
export function buildMaterialSlotPlan<T extends object>(
|
|
403
406
|
materialGroups: readonly (readonly T[])[],
|
|
407
|
+
bindingClass?: (material: T, owner: number) => string,
|
|
404
408
|
): MaterialSlotPlan<T> {
|
|
405
|
-
const slotByMaterial = new Map<T, number
|
|
409
|
+
const slotByMaterial = new Map<T, Map<string, number>>();
|
|
406
410
|
const slots: T[] = [];
|
|
407
411
|
const slotOwners: number[] = [];
|
|
408
412
|
const slotIndices = materialGroups.map((materials, ownerIndex) =>
|
|
409
413
|
materials.map((material) => {
|
|
410
|
-
const
|
|
414
|
+
const resourceClass = bindingClass?.(material, ownerIndex) ?? '';
|
|
415
|
+
let materialClasses = slotByMaterial.get(material);
|
|
416
|
+
if (materialClasses === undefined) {
|
|
417
|
+
materialClasses = new Map();
|
|
418
|
+
slotByMaterial.set(material, materialClasses);
|
|
419
|
+
}
|
|
420
|
+
const cached = materialClasses.get(resourceClass);
|
|
411
421
|
if (cached !== undefined) return cached;
|
|
412
422
|
const slot = slots.length;
|
|
413
423
|
slots.push(material);
|
|
414
424
|
slotOwners.push(ownerIndex);
|
|
415
|
-
|
|
425
|
+
materialClasses.set(resourceClass, slot);
|
|
416
426
|
return slot;
|
|
417
427
|
}),
|
|
418
428
|
);
|
|
@@ -482,6 +492,7 @@ function limitRowsToMeshSsboCapacity<T>(rows: readonly T[], availableSlots: numb
|
|
|
482
492
|
export type RecordProfileRunner = <T>(phase: RenderRecordPhase, action: () => T) => T;
|
|
483
493
|
|
|
484
494
|
export interface CubeCaptureFrameInput {
|
|
495
|
+
readonly captureDispatch?: readonly DispatchEntry[];
|
|
485
496
|
readonly snapshots: readonly CubeCameraSnapshot[];
|
|
486
497
|
readonly scheduler: import('../capture/scheduler').CubeCaptureScheduler;
|
|
487
498
|
readonly state: CubeCaptureGraphState;
|
|
@@ -659,15 +670,19 @@ async function mapReflectionFallbackReadback(
|
|
|
659
670
|
for (let y = 0; y < request.height; y += 1) {
|
|
660
671
|
for (let x = 0; x < request.width; x += 1) {
|
|
661
672
|
const offset = y * request.bytesPerRow + x * 8;
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
673
|
+
// Validation above already rejects non-finite half floats. Scan the
|
|
674
|
+
// raw RGB magnitudes (both signed zero encodings are empty) without
|
|
675
|
+
// allocating/decoding millions of background pixels each frame.
|
|
676
|
+
const red = view.getUint16(offset, true);
|
|
677
|
+
const green = view.getUint16(offset + 2, true);
|
|
678
|
+
const blue = view.getUint16(offset + 4, true);
|
|
679
|
+
if ((red & 0x7fff) !== 0 || (green & 0x7fff) !== 0 || (blue & 0x7fff) !== 0) {
|
|
680
|
+
linearHdr = [
|
|
681
|
+
halfFloatToNumber(red),
|
|
682
|
+
halfFloatToNumber(green),
|
|
683
|
+
halfFloatToNumber(blue),
|
|
684
|
+
halfFloatToNumber(view.getUint16(offset + 6, true)),
|
|
685
|
+
];
|
|
671
686
|
y = request.height;
|
|
672
687
|
break;
|
|
673
688
|
}
|
|
@@ -1854,15 +1869,21 @@ export function recordFrame(
|
|
|
1854
1869
|
(volumetricFog?.status === 'degraded' && acceptedFallback !== undefined);
|
|
1855
1870
|
|
|
1856
1871
|
let preparedGpuDriven: PreparedGpuDrivenFrame | undefined;
|
|
1872
|
+
let materialBindingClasses: ReadonlyMap<string, string> | undefined;
|
|
1857
1873
|
const abortPreparedGpuDriven = (): void => {
|
|
1858
1874
|
preparedGpuDriven?._abortResourceReplacement?.();
|
|
1859
1875
|
};
|
|
1860
1876
|
const cubeCaptureWork = prepareCubeCapture(internals, cubeCapture, camera);
|
|
1861
1877
|
const reflectionFallbackCandidate = cubeCapture?.reflectionProbes?.fallbackDemand === true;
|
|
1862
|
-
//
|
|
1863
|
-
//
|
|
1864
|
-
//
|
|
1865
|
-
|
|
1878
|
+
// Capture views have independent draw ownership; display-camera GPU work
|
|
1879
|
+
// remains active while their faces and SSR fallback attachments are recorded.
|
|
1880
|
+
// ProbeBlendRecord is an object-level fragment ABI. The scene-index GPU
|
|
1881
|
+
// lane has no binding for that record yet, so claiming a probe-bearing
|
|
1882
|
+
// row would silently fall back to Skylight and make local diffuse probes
|
|
1883
|
+
// visually ineffective. Keep the whole frame on the CPU producer until
|
|
1884
|
+
// the scene-index lane carries the same record contract.
|
|
1885
|
+
const probeBlendFrame = renderables.some((entry) => entry.probeBlendRecord !== undefined);
|
|
1886
|
+
const frameGpuDriven = probeBlendFrame ? undefined : gpuDriven;
|
|
1866
1887
|
|
|
1867
1888
|
// Validate first so user meshes are resident in the same frame. The GPU
|
|
1868
1889
|
// owner consumes this producer-owned map together with the builtin mesh
|
|
@@ -1914,6 +1935,41 @@ export function recordFrame(
|
|
|
1914
1935
|
? projectValidatedRows(validatedProjection, renderables)
|
|
1915
1936
|
: validatedProjection;
|
|
1916
1937
|
|
|
1938
|
+
// S_fallback is the second output of the built-in Standard PBR BRDF. A
|
|
1939
|
+
// graph may still carry the detached owner tickets for inspection, but
|
|
1940
|
+
// the MRT is admitted only when every CPU-rendered primary row in this
|
|
1941
|
+
// frame uses that exact output contract. Unsupported compositions remain
|
|
1942
|
+
// fail-closed for SSR instead of submitting a device-invalid command.
|
|
1943
|
+
const sceneInputs =
|
|
1944
|
+
validatedForResidency.length > 0 &&
|
|
1945
|
+
validatedForResidency.every(
|
|
1946
|
+
(entry) => entry.source.material.materialShaderId === 'forgeax::default-standard-pbr',
|
|
1947
|
+
);
|
|
1948
|
+
const ssrAdmission =
|
|
1949
|
+
ssrDependencies === undefined
|
|
1950
|
+
? undefined
|
|
1951
|
+
: admitSsrSpatial({
|
|
1952
|
+
camera,
|
|
1953
|
+
environment: {
|
|
1954
|
+
lane: standard.prepared.renderPath === 'deferred' ? 'deferred' : 'forward',
|
|
1955
|
+
m0: ssrDependencies.admission,
|
|
1956
|
+
sceneInputs,
|
|
1957
|
+
// Standard geometry produces current motion/coverage in this
|
|
1958
|
+
// graph, including its first frame. Prior history is optional.
|
|
1959
|
+
temporal: sceneInputs,
|
|
1960
|
+
reflectionFallback: ssrDependencies.reflectionFallback !== undefined,
|
|
1961
|
+
capabilities: {
|
|
1962
|
+
compute: internals.device.caps.compute,
|
|
1963
|
+
storageTexture: internals.device.caps.storageTexture,
|
|
1964
|
+
rgba16floatRenderable: internals.device.caps.rgba16floatRenderable,
|
|
1965
|
+
r32floatSampledStorage: ssrDependencies.format?.verdict === 'admitted',
|
|
1966
|
+
},
|
|
1967
|
+
recovery: true,
|
|
1968
|
+
},
|
|
1969
|
+
});
|
|
1970
|
+
frameState.reflectionFallbackDemand =
|
|
1971
|
+
(reflectionFallbackCandidate || ssrAdmission?.status === 'admitted') && sceneInputs;
|
|
1972
|
+
|
|
1917
1973
|
if (frameGpuDriven !== undefined) {
|
|
1918
1974
|
const gpuDrivenMeshes = new Map(
|
|
1919
1975
|
gpuDrivenMeshesForFrame(internals, pipelineState, worlds, frameGpuDriven.scene),
|
|
@@ -1930,10 +1986,28 @@ export function recordFrame(
|
|
|
1930
1986
|
);
|
|
1931
1987
|
if (slot !== undefined) gpuDrivenMeshes.set(slot, row.mesh);
|
|
1932
1988
|
}
|
|
1933
|
-
|
|
1934
|
-
|
|
1989
|
+
// Resolve one producer artifact for every prepared draw. COLOR_0 is a
|
|
1990
|
+
// per-geometry ABI axis, so a residency-wide `.some(color)` would pair
|
|
1991
|
+
// a no-color draw with the colored receipt (or vice versa) and collapse
|
|
1992
|
+
// two distinct pipeline/projection identities before indirect record.
|
|
1993
|
+
materialBindingClasses = projectMaterialBindingClasses(
|
|
1994
|
+
validatedForResidency,
|
|
1995
|
+
transparentDispatch,
|
|
1996
|
+
cubeCapture?.reflectionProbes,
|
|
1935
1997
|
);
|
|
1936
|
-
const
|
|
1998
|
+
const { materialArtifacts, shadowMaterialArtifacts, firstArtifact, firstSkinArtifact } =
|
|
1999
|
+
collectGpuDrivenMaterialArtifacts({
|
|
2000
|
+
rows: validatedForResidency,
|
|
2001
|
+
shadowRows: validatedShadowForResidency ?? [],
|
|
2002
|
+
dispatch: transparentDispatch,
|
|
2003
|
+
shadowDispatch: shadowCasterProjection?.dispatch ?? [],
|
|
2004
|
+
resolve: internals.getMaterialShaderArtifact,
|
|
2005
|
+
clustered:
|
|
2006
|
+
standard.kind === 'clustered' &&
|
|
2007
|
+
(standard.prepared.local.length > 0 ||
|
|
2008
|
+
frameState.installedPipelineConfig?.ssao?.enabled === true),
|
|
2009
|
+
reflectionFallback: frameState.reflectionFallbackDemand === true,
|
|
2010
|
+
});
|
|
1937
2011
|
const paletteUploadBytes = validatedForResidency.reduce(
|
|
1938
2012
|
(total, row) => total + (row.source.skin?.uploadBytes ?? 0),
|
|
1939
2013
|
0,
|
|
@@ -1944,14 +2018,7 @@ export function recordFrame(
|
|
|
1944
2018
|
meshBySlot: gpuDrivenMeshes,
|
|
1945
2019
|
viewBindGroupLayout: pipelineState.viewBindGroupLayout,
|
|
1946
2020
|
meshResidencyEpoch: internals.gpuStore.meshResidencyEpoch,
|
|
1947
|
-
|
|
1948
|
-
// Cluster bindings also carry screen-space ambient occlusion. Admit
|
|
1949
|
-
// the scene-index variant only when none of those surface inputs are
|
|
1950
|
-
// required; a zero local-light count alone does not establish that.
|
|
1951
|
-
hdrp:
|
|
1952
|
-
standard.kind === 'clustered' &&
|
|
1953
|
-
(standard.prepared.local.length > 0 ||
|
|
1954
|
-
frameState.installedPipelineConfig?.ssao?.enabled === true),
|
|
2021
|
+
materialBindingClasses,
|
|
1955
2022
|
...(frameGpuDriven.activeEntityKeys === undefined
|
|
1956
2023
|
? {}
|
|
1957
2024
|
: { activeEntityKeys: frameGpuDriven.activeEntityKeys }),
|
|
@@ -1970,9 +2037,14 @@ export function recordFrame(
|
|
|
1970
2037
|
paletteUploadBytes,
|
|
1971
2038
|
},
|
|
1972
2039
|
}),
|
|
1973
|
-
...(
|
|
1974
|
-
...(
|
|
1975
|
-
|
|
2040
|
+
...(firstArtifact === undefined ? {} : { materialArtifact: firstArtifact }),
|
|
2041
|
+
...(firstSkinArtifact === undefined ? {} : { materialSkinArtifact: firstSkinArtifact }),
|
|
2042
|
+
...(materialArtifacts.size === 0 ? {} : { materialArtifacts }),
|
|
2043
|
+
...(shadowMaterialArtifacts.size === 0 ? {} : { shadowMaterialArtifacts }),
|
|
2044
|
+
materialPipelineState: pipelineState,
|
|
2045
|
+
...(internals.getMaterialShaderPipelineEntry === undefined
|
|
2046
|
+
? {}
|
|
2047
|
+
: { materialPipelineFactory: internals.getMaterialShaderPipelineEntry }),
|
|
1976
2048
|
...(shadowCasterDrawKeys === undefined ? {} : { shadowCasterDrawKeys }),
|
|
1977
2049
|
...(shadowCasterMembership === undefined ? {} : { shadowCasterMembership }),
|
|
1978
2050
|
});
|
|
@@ -2062,40 +2134,22 @@ export function recordFrame(
|
|
|
2062
2134
|
// the current frame. This keeps the graph topology and its execution
|
|
2063
2135
|
// closure on the same prepared GPU-owned draw set.
|
|
2064
2136
|
|
|
2065
|
-
//
|
|
2066
|
-
//
|
|
2067
|
-
//
|
|
2068
|
-
//
|
|
2069
|
-
//
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
);
|
|
2075
|
-
const ssrAdmission =
|
|
2076
|
-
ssrDependencies === undefined
|
|
2137
|
+
// RenderExtent is an authored DynamicResolution path. The native TAA path
|
|
2138
|
+
// intentionally has no extent object, so every Standard consumer keeps the
|
|
2139
|
+
// exact surface domain even when a surface is not 8-pixel aligned. An
|
|
2140
|
+
// adaptive range remains unavailable until a renderer-owned timing/
|
|
2141
|
+
// controller chain exists; do not turn maxScale into a fake performance
|
|
2142
|
+
// decision. Fixed minScale=maxScale is the only extent currently admitted.
|
|
2143
|
+
const renderExtent =
|
|
2144
|
+
camera.dynamicResolution === undefined ||
|
|
2145
|
+
camera.dynamicResolution.minScale !== camera.dynamicResolution.maxScale
|
|
2077
2146
|
? undefined
|
|
2078
|
-
:
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
sceneInputs,
|
|
2084
|
-
// Standard geometry produces current motion/coverage in this
|
|
2085
|
-
// graph, including its first frame. Prior history is optional.
|
|
2086
|
-
temporal: sceneInputs,
|
|
2087
|
-
reflectionFallback: ssrDependencies.reflectionFallback !== undefined,
|
|
2088
|
-
capabilities: {
|
|
2089
|
-
compute: internals.device.caps.compute,
|
|
2090
|
-
storageTexture: internals.device.caps.storageTexture,
|
|
2091
|
-
rgba16floatRenderable: internals.device.caps.rgba16floatRenderable,
|
|
2092
|
-
r32floatSampledStorage: ssrDependencies.format?.verdict === 'admitted',
|
|
2093
|
-
},
|
|
2094
|
-
recovery: true,
|
|
2095
|
-
},
|
|
2147
|
+
: deriveRenderExtent({
|
|
2148
|
+
outputWidth: Math.max(1, internals.canvas.width),
|
|
2149
|
+
outputHeight: Math.max(1, internals.canvas.height),
|
|
2150
|
+
requestedScale: camera.dynamicResolution.minScale,
|
|
2151
|
+
generation: internals.deviceScope?.generation ?? 0,
|
|
2096
2152
|
});
|
|
2097
|
-
frameState.reflectionFallbackDemand =
|
|
2098
|
-
(reflectionFallbackCandidate || ssrAdmission?.status === 'admitted') && sceneInputs;
|
|
2099
2153
|
const preflightGraph = runRecordProfilePhase(profilePhase, 'record/render-graph', () =>
|
|
2100
2154
|
ensureCompiledFrameGraph(
|
|
2101
2155
|
internals,
|
|
@@ -2117,6 +2171,7 @@ export function recordFrame(
|
|
|
2117
2171
|
standard,
|
|
2118
2172
|
undefined,
|
|
2119
2173
|
ssrAdmission,
|
|
2174
|
+
renderExtent,
|
|
2120
2175
|
),
|
|
2121
2176
|
);
|
|
2122
2177
|
if (preflightGraph === null) {
|
|
@@ -2214,6 +2269,12 @@ export function recordFrame(
|
|
|
2214
2269
|
environmentSignature,
|
|
2215
2270
|
fogSignature,
|
|
2216
2271
|
deviceGeneration: internals.deviceScope?.generation ?? 0,
|
|
2272
|
+
...(renderExtent === undefined
|
|
2273
|
+
? {}
|
|
2274
|
+
: {
|
|
2275
|
+
internalWidth: renderExtent.internalWidth,
|
|
2276
|
+
internalHeight: renderExtent.internalHeight,
|
|
2277
|
+
}),
|
|
2217
2278
|
...(camera.historyVersion === undefined ? {} : { historyVersion: camera.historyVersion }),
|
|
2218
2279
|
historyValid: false,
|
|
2219
2280
|
currentUnjitteredViewProjection,
|
|
@@ -2371,6 +2432,7 @@ export function recordFrame(
|
|
|
2371
2432
|
transparentDispatch,
|
|
2372
2433
|
foldBuckets,
|
|
2373
2434
|
validatedShadowForResidency ?? [],
|
|
2435
|
+
materialBindingClasses,
|
|
2374
2436
|
),
|
|
2375
2437
|
);
|
|
2376
2438
|
const validatedOrdered = dispatchPlan.validatedOrdered;
|
|
@@ -2594,6 +2656,7 @@ export function recordFrame(
|
|
|
2594
2656
|
clear,
|
|
2595
2657
|
targetW,
|
|
2596
2658
|
targetH,
|
|
2659
|
+
...(renderExtent === undefined ? {} : { extent: renderExtent }),
|
|
2597
2660
|
currentTexture,
|
|
2598
2661
|
camera: recordCamera,
|
|
2599
2662
|
tonemapActive,
|
|
@@ -2656,6 +2719,9 @@ export function recordFrame(
|
|
|
2656
2719
|
...(cubeCapture?.reflectionProbes === undefined
|
|
2657
2720
|
? {}
|
|
2658
2721
|
: { reflectionProbes: cubeCapture.reflectionProbes }),
|
|
2722
|
+
...(cubeCapture?.captureDispatch === undefined
|
|
2723
|
+
? {}
|
|
2724
|
+
: { captureDispatch: cubeCapture.captureDispatch }),
|
|
2659
2725
|
pointsLines: pointsLinesOwner,
|
|
2660
2726
|
materialBgAssemblyCache: frameState.materialBgAssemblyCache,
|
|
2661
2727
|
...(onRenderableDraw === undefined ? {} : { onRenderableDraw }),
|
|
@@ -2669,7 +2735,10 @@ export function recordFrame(
|
|
|
2669
2735
|
...(profilePhase !== undefined ? { profilePhase } : {}),
|
|
2670
2736
|
};
|
|
2671
2737
|
uploadMaterialUniforms(passCtx);
|
|
2672
|
-
const fallbackReadbackRequest =
|
|
2738
|
+
const fallbackReadbackRequest =
|
|
2739
|
+
internals.captureReflectionFallbackReadback === true
|
|
2740
|
+
? createReflectionFallbackReadbackRequest(internals, frameState)
|
|
2741
|
+
: undefined;
|
|
2673
2742
|
if (fallbackReadbackRequest !== undefined) {
|
|
2674
2743
|
frameState.reflectionFallbackReadback = fallbackReadbackRequest;
|
|
2675
2744
|
}
|
|
@@ -2779,21 +2848,20 @@ export function recordFrame(
|
|
|
2779
2848
|
if (!submitted && fallbackReadbackRequest !== undefined) {
|
|
2780
2849
|
internals.device.destroyBuffer(fallbackReadbackRequest.buffer);
|
|
2781
2850
|
}
|
|
2851
|
+
const fallbackSource =
|
|
2852
|
+
frameState.reflectionFallbackObservationSource as RenderFrameState['reflectionFallbackObservationSource'];
|
|
2782
2853
|
const reflectionFallbackCompletion = cubeCapture?.reflectionProbes?.completeSubmission(
|
|
2783
2854
|
submitted,
|
|
2784
2855
|
completion,
|
|
2785
|
-
|
|
2856
|
+
fallbackSource === undefined
|
|
2786
2857
|
? undefined
|
|
2787
2858
|
: {
|
|
2788
|
-
format:
|
|
2789
|
-
size:
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
graphGeneration: fallbackReadbackRequest.expected.graphGeneration,
|
|
2795
|
-
textureIdentity: fallbackReadbackRequest.expected.textureIdentity,
|
|
2796
|
-
readback: fallbackReadback,
|
|
2859
|
+
format: fallbackSource.descriptor.format,
|
|
2860
|
+
size: fallbackSource.descriptor.size,
|
|
2861
|
+
frameId: fallbackSource.frameId,
|
|
2862
|
+
graphGeneration: frameState.graphGeneration,
|
|
2863
|
+
textureIdentity: getTextureIdentity(fallbackSource.texture),
|
|
2864
|
+
...(fallbackReadback === undefined ? {} : { readback: fallbackReadback }),
|
|
2797
2865
|
},
|
|
2798
2866
|
frameState.reflectionFallbackDemand,
|
|
2799
2867
|
);
|
|
@@ -3330,6 +3398,7 @@ export function buildDispatchPlan(
|
|
|
3330
3398
|
transparentDispatch: readonly DispatchEntry[],
|
|
3331
3399
|
foldBuckets: readonly FoldBucket[],
|
|
3332
3400
|
shadowValidated: readonly ValidatedRenderable[] = [],
|
|
3401
|
+
materialBindingClasses?: ReadonlyMap<string, string>,
|
|
3333
3402
|
): {
|
|
3334
3403
|
validatedOrdered: readonly ValidatedRenderable[];
|
|
3335
3404
|
shadowValidatedOrdered: readonly ValidatedRenderable[];
|
|
@@ -3411,7 +3480,14 @@ export function buildDispatchPlan(
|
|
|
3411
3480
|
}
|
|
3412
3481
|
return entry.source.materials.length > 0 ? entry.source.materials : [entry.source.material];
|
|
3413
3482
|
});
|
|
3414
|
-
const materialSlotPlan = buildMaterialSlotPlan(materialGroups)
|
|
3483
|
+
const materialSlotPlan = buildMaterialSlotPlan(materialGroups, (material, owner) => {
|
|
3484
|
+
const row = materialRows[owner];
|
|
3485
|
+
return row === undefined
|
|
3486
|
+
? ''
|
|
3487
|
+
: (materialBindingClasses?.get(
|
|
3488
|
+
materialBindingKey(row.source, material.materialHandle ?? -1),
|
|
3489
|
+
) ?? '');
|
|
3490
|
+
});
|
|
3415
3491
|
let materialSlotIndices = materialSlotPlan.slotIndices;
|
|
3416
3492
|
let materialSlots = materialSlotPlan.slots;
|
|
3417
3493
|
let materialSlotOwners = materialSlotPlan.slotOwners.map((index) => {
|
|
@@ -73,6 +73,23 @@ import type { _InternalRenderPipelineContext, MaterialShaderPipelineEntry } from
|
|
|
73
73
|
import { MATERIAL_PER_ENTITY_STRIDE } from './render-context';
|
|
74
74
|
import { POINTS_LINES_VIEW_SLOT_STRIDE, writePointsLinesViewUbo } from './view-ubo';
|
|
75
75
|
|
|
76
|
+
/** Temporal ignores authored color entry points; opaque duplicates are idempotent. */
|
|
77
|
+
export function sameOpaqueTemporalDraw(a: DispatchEntry, b: DispatchEntry): boolean {
|
|
78
|
+
return (
|
|
79
|
+
(isStandardPbrMaterialShader(a.materialShaderId) ||
|
|
80
|
+
(a.tags.SurfaceKind === 'standard' &&
|
|
81
|
+
b.tags.SurfaceKind === 'standard' &&
|
|
82
|
+
a.tags.SurfaceModule === b.tags.SurfaceModule)) &&
|
|
83
|
+
a.materialShaderId === b.materialShaderId &&
|
|
84
|
+
a.renderState?.blend === undefined &&
|
|
85
|
+
b.renderState?.blend === undefined &&
|
|
86
|
+
a.renderState?.stencil === undefined &&
|
|
87
|
+
b.renderState?.stencil === undefined &&
|
|
88
|
+
a.stencilReference === b.stencilReference &&
|
|
89
|
+
renderStateHash(a.renderState) === renderStateHash(b.renderState)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
76
93
|
type GeometryInstanceDraw = {
|
|
77
94
|
readonly instanceBuffer: Buffer;
|
|
78
95
|
readonly instanceBindGroup: BindGroup;
|
|
@@ -133,6 +150,25 @@ type GeometryRecordProfileSegment = 'material-bind-groups' | 'pipeline-selection
|
|
|
133
150
|
|
|
134
151
|
type GeometryRenderState = ReturnType<typeof geometryRenderStateForTopology>;
|
|
135
152
|
|
|
153
|
+
/** Coverage is a dedicated temporal material variant, not a color/alpha tap. */
|
|
154
|
+
export function variantSetForCoveragePass(
|
|
155
|
+
variantSet: string | undefined,
|
|
156
|
+
coverageOnly: boolean,
|
|
157
|
+
): string | undefined {
|
|
158
|
+
if (!coverageOnly) return variantSet;
|
|
159
|
+
if (variantSet?.includes('COVERAGE_ONLY=')) return variantSet;
|
|
160
|
+
return variantSet === undefined || variantSet === ''
|
|
161
|
+
? 'COVERAGE_ONLY=true'
|
|
162
|
+
: `${variantSet}+COVERAGE_ONLY=true`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function isHdrGeometryTarget(
|
|
166
|
+
tonemapActive: boolean,
|
|
167
|
+
colorFormatOverride: GPUTextureFormat | undefined,
|
|
168
|
+
): boolean {
|
|
169
|
+
return colorFormatOverride === undefined ? tonemapActive : colorFormatOverride === 'rgba16float';
|
|
170
|
+
}
|
|
171
|
+
|
|
136
172
|
function gpuDrivenDrawIndicesBySubmesh(
|
|
137
173
|
source: RenderableSnapshot,
|
|
138
174
|
mesh: _InternalRenderPipelineContext['validatedOrdered'][number]['mesh'],
|
|
@@ -319,11 +355,12 @@ export function effectiveMaterialLayoutIdentity(
|
|
|
319
355
|
export function geometryRenderStateForPass(
|
|
320
356
|
base: GeometryRenderState,
|
|
321
357
|
passKind: PassKind,
|
|
358
|
+
coverageOnly = false,
|
|
322
359
|
): GeometryRenderState {
|
|
323
360
|
if (passKind !== 'temporal') return base;
|
|
324
361
|
return {
|
|
325
362
|
...base,
|
|
326
|
-
depthWriteEnabled:
|
|
363
|
+
depthWriteEnabled: coverageOnly,
|
|
327
364
|
depthCompare: 'less-equal' as const,
|
|
328
365
|
};
|
|
329
366
|
}
|
|
@@ -434,6 +471,7 @@ export function recordGeometryDraws(
|
|
|
434
471
|
passKind: PassKind = 'forward',
|
|
435
472
|
selectedDispatch?: readonly DispatchEntry[],
|
|
436
473
|
colorFormats: readonly GPUTextureFormat[] = [],
|
|
474
|
+
coverageOnly = false,
|
|
437
475
|
): void {
|
|
438
476
|
const {
|
|
439
477
|
runtime,
|
|
@@ -457,7 +495,11 @@ export function recordGeometryDraws(
|
|
|
457
495
|
}
|
|
458
496
|
const passes = byMaterial.get(dispatch.materialHandle);
|
|
459
497
|
if (passes === undefined) byMaterial.set(dispatch.materialHandle, [dispatch]);
|
|
460
|
-
else
|
|
498
|
+
else if (
|
|
499
|
+
passKind !== 'temporal' ||
|
|
500
|
+
!passes.some((previous) => sameOpaqueTemporalDraw(previous, dispatch))
|
|
501
|
+
)
|
|
502
|
+
passes.push(dispatch);
|
|
461
503
|
}
|
|
462
504
|
const diagnosticsEnabled = materialDiagnosticsEnabled();
|
|
463
505
|
const colorFormatOverride = c.transparentColorFormat as GPUTextureFormat | undefined;
|
|
@@ -470,7 +512,9 @@ export function recordGeometryDraws(
|
|
|
470
512
|
// numeric domain rather than the camera's tone-map switch, otherwise the
|
|
471
513
|
// LDR/OETF fragment entry point is encoded once here and again by the
|
|
472
514
|
// output transform.
|
|
473
|
-
const isHdrTarget = tonemapActive
|
|
515
|
+
const isHdrTarget = isHdrGeometryTarget(tonemapActive, colorFormatOverride);
|
|
516
|
+
const withCoverageVariant = (variantSet: string | undefined): string | undefined =>
|
|
517
|
+
variantSetForCoveragePass(variantSet, coverageOnly);
|
|
474
518
|
let lastVertexBuffer: GpuBuffer | null = null;
|
|
475
519
|
let lastIndexBuffer: GpuBuffer | null = null;
|
|
476
520
|
const bindingState: GeometryBindingState = {
|
|
@@ -520,6 +564,7 @@ export function recordGeometryDraws(
|
|
|
520
564
|
fragmentEntry?: string,
|
|
521
565
|
textureMask?: number,
|
|
522
566
|
): MaterialShaderPipelineEntry | null => {
|
|
567
|
+
const pipelineVariantSet = withCoverageVariant(variantSet);
|
|
523
568
|
// The fallback MRT is an extension of the built-in Standard PBR output
|
|
524
569
|
// contract only. The render pass may carry a second attachment whenever
|
|
525
570
|
// another renderable needs S_fallback, but shaders such as unlit, sprite,
|
|
@@ -545,7 +590,7 @@ export function recordGeometryDraws(
|
|
|
545
590
|
cached.renderStateKey === renderStateKey &&
|
|
546
591
|
cached.topology === topology &&
|
|
547
592
|
cached.indexFormat === indexFormat &&
|
|
548
|
-
cached.variantSet ===
|
|
593
|
+
cached.variantSet === pipelineVariantSet &&
|
|
549
594
|
cached.vertexEntry === vertexEntry &&
|
|
550
595
|
cached.fragmentEntry === fragmentEntry &&
|
|
551
596
|
cached.textureMask === textureMask &&
|
|
@@ -562,10 +607,10 @@ export function recordGeometryDraws(
|
|
|
562
607
|
const resolvedVariantSetResult =
|
|
563
608
|
runtime.getMaterialArtifact?.(materialShaderId) !== undefined
|
|
564
609
|
? ({ ok: true, value: undefined } as const)
|
|
565
|
-
:
|
|
610
|
+
: pipelineVariantSet === undefined &&
|
|
566
611
|
(materialShaderId === 'forgeax::sprite' || materialShaderId === 'forgeax::sprite-lit')
|
|
567
612
|
? ({ ok: true, value: undefined } as const)
|
|
568
|
-
: variantSetFromVertexLayoutProjection(layoutProjection,
|
|
613
|
+
: variantSetFromVertexLayoutProjection(layoutProjection, pipelineVariantSet);
|
|
569
614
|
if (!resolvedVariantSetResult.ok) {
|
|
570
615
|
runtime.errorRegistry.fire(resolvedVariantSetResult.error);
|
|
571
616
|
return null;
|
|
@@ -620,7 +665,7 @@ export function recordGeometryDraws(
|
|
|
620
665
|
renderStateKey,
|
|
621
666
|
topology,
|
|
622
667
|
indexFormat,
|
|
623
|
-
variantSet,
|
|
668
|
+
variantSet: pipelineVariantSet,
|
|
624
669
|
vertexEntry,
|
|
625
670
|
fragmentEntry,
|
|
626
671
|
passKind,
|
|
@@ -878,7 +923,9 @@ export function recordGeometryDraws(
|
|
|
878
923
|
),
|
|
879
924
|
);
|
|
880
925
|
if (!skinVariantSetResult.ok) runtime.errorRegistry.fire(skinVariantSetResult.error);
|
|
881
|
-
const skinVariantSet = skinVariantSetResult.ok
|
|
926
|
+
const skinVariantSet = skinVariantSetResult.ok
|
|
927
|
+
? withCoverageVariant(skinVariantSetResult.value)
|
|
928
|
+
: undefined;
|
|
882
929
|
const skinPsoProbe =
|
|
883
930
|
skinResources !== null && skinVariantSetResult.ok
|
|
884
931
|
? (runtime.getMaterialShaderPipeline?.(
|
|
@@ -1196,7 +1243,11 @@ export function recordGeometryDraws(
|
|
|
1196
1243
|
blend: selectedRenderState?.blend ?? SPRITE_PREMULTIPLIED_ALPHA_BLEND,
|
|
1197
1244
|
}
|
|
1198
1245
|
: geometryRenderStateForTopology(smTopology, selectedRenderState);
|
|
1199
|
-
const pipelineRenderState = geometryRenderStateForPass(
|
|
1246
|
+
const pipelineRenderState = geometryRenderStateForPass(
|
|
1247
|
+
basePipelineRenderState,
|
|
1248
|
+
passKind,
|
|
1249
|
+
coverageOnly,
|
|
1250
|
+
);
|
|
1200
1251
|
let smPipelineHandle: typeof pipelineState.unlitPipeline;
|
|
1201
1252
|
let materialGroup2Contract: 'mesh' | 'skin' | 'cluster' | 'skin-cluster' | undefined;
|
|
1202
1253
|
let materialPipelineEntry: MaterialShaderPipelineEntry | null = null;
|