@forgeax/engine-render 0.1.23 → 0.1.25
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 +231 -10
- package/dist/assembly/bundler-contract.d.ts +9 -0
- package/dist/assembly/bundler-contract.d.ts.map +1 -0
- package/dist/assembly/device-feature-admission.d.ts +8 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -1
- package/dist/assembly/extended-lighting-fallback.d.ts +13 -0
- package/dist/assembly/extended-lighting-fallback.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +7 -243
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +3 -2
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/standard-layer-projection.d.ts +10 -0
- package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -0
- package/dist/assembly/material/surface-projection.d.ts +24 -0
- package/dist/assembly/material/surface-projection.d.ts.map +1 -0
- package/dist/assembly/material-shader-policy.d.ts +188 -0
- package/dist/assembly/material-shader-policy.d.ts.map +1 -0
- package/dist/assembly/material-shader-prewarm.d.ts +21 -0
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/mesh-ssbo-grow.d.ts +88 -0
- package/dist/assembly/mesh-ssbo-grow.d.ts.map +1 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts +14 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -0
- package/dist/assembly/recovery/generation.d.ts +46 -0
- package/dist/assembly/recovery/generation.d.ts.map +1 -0
- package/dist/assembly/recovery/recovery-attempt.d.ts +63 -0
- package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts +115 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -0
- package/dist/assembly/renderer-facade.d.ts +10 -0
- package/dist/assembly/renderer-facade.d.ts.map +1 -0
- package/dist/assembly/renderer-frame-transaction.d.ts +17 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-helpers.d.ts +19 -0
- package/dist/assembly/renderer-helpers.d.ts.map +1 -0
- package/dist/assembly/renderer-lifecycle.d.ts +34 -0
- package/dist/assembly/renderer-lifecycle.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +15 -0
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready-contract.d.ts +9 -0
- package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +55 -0
- package/dist/assembly/webgpu-ready.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +152 -0
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -0
- package/dist/assembly/webgpu-vertex-layouts.d.ts +89 -0
- package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -0
- package/dist/assets/asset-decoders.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/{chunk-FF7K3FSO.mjs → chunk-ADHHVYLW.mjs} +89 -89
- package/dist/chunk-ADHHVYLW.mjs.map +1 -0
- package/dist/{chunk-YALPS44A.mjs → chunk-E34VL5VI.mjs} +47 -47
- package/dist/chunk-E34VL5VI.mjs.map +1 -0
- package/dist/{chunk-4L3P6DT5.mjs → chunk-GE3SDD72.mjs} +37 -5
- package/dist/chunk-GE3SDD72.mjs.map +1 -0
- package/dist/{chunk-HZUPSYW7.mjs → chunk-HKXTW355.mjs} +105 -15
- package/dist/chunk-HKXTW355.mjs.map +1 -0
- package/dist/chunk-JSEDTZYS.mjs +413 -0
- package/dist/chunk-JSEDTZYS.mjs.map +1 -0
- package/dist/{chunk-FBC4R44J.mjs → chunk-KM2NOX2I.mjs} +57 -57
- package/dist/chunk-KM2NOX2I.mjs.map +1 -0
- package/dist/{chunk-DIYW3M5D.mjs → chunk-N3RT2EUR.mjs} +2288 -2238
- package/dist/chunk-N3RT2EUR.mjs.map +1 -0
- package/dist/{chunk-ZUWKAZ2I.mjs → chunk-TCLDX7SZ.mjs} +1167 -368
- package/dist/chunk-TCLDX7SZ.mjs.map +1 -0
- package/dist/{chunk-QODA5UKU.mjs → chunk-ZZ4YQ474.mjs} +2 -2
- package/dist/chunk-ZZ4YQ474.mjs.map +1 -0
- package/dist/components/instances.d.ts +13 -31
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +20688 -16314
- 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 +24 -4
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/environment/frame.d.ts +5 -0
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/inspection.d.ts +7 -0
- package/dist/environment/inspection.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +20 -2
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +58 -2
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +13 -0
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +899 -0
- package/dist/extract/contracts.d.ts.map +1 -0
- package/dist/features/host.d.ts +2 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +3 -0
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics-store.d.ts +2 -0
- package/dist/features/prepared-graphics-store.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +34 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +5 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +7 -6
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +7 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +27 -9
- package/dist/index.mjs.map +1 -1
- package/dist/instance-buffer-cache.d.ts +7 -1
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +101 -0
- package/dist/instances.d.ts.map +1 -0
- package/dist/internal.mjs +6 -6
- package/dist/light-buffer-layout.d.ts +3 -0
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts +96 -11
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +56 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/occlusion-proxy.d.ts +4 -0
- package/dist/occlusion-proxy.d.ts.map +1 -0
- package/dist/pbr-pipeline.d.ts +32 -9
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/points-lines/prepare.d.ts +3 -0
- package/dist/points-lines/prepare.d.ts.map +1 -1
- package/dist/points-lines/standard-owner.d.ts +33 -0
- package/dist/points-lines/standard-owner.d.ts.map +1 -0
- package/dist/record/frame-snapshot.d.ts +18 -2
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +14 -2
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +36 -4
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -17
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +11 -3
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/recovery-pipeline.d.ts +30 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -0
- package/dist/record/render-context.d.ts +28 -5
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +11 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +1 -1
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +65 -0
- package/dist/recovery/render-system-candidate.d.ts.map +1 -0
- package/dist/render-contract.d.ts +68 -7
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +16 -0
- package/dist/render-system-extract-tail.d.ts.map +1 -0
- package/dist/render-system-extract.d.ts +180 -22
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +131 -4
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene-types.d.ts +2 -0
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +31 -1
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/systems/skin-palette-allocator.d.ts +6 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -6
- package/dist/temporal/taa-history-store.d.ts +15 -1
- package/dist/temporal/taa-history-store.d.ts.map +1 -1
- package/dist/temporal/transaction.d.ts +5 -0
- package/dist/temporal/transaction.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/device-feature-admission.unit.test.ts +6 -0
- package/src/__tests__/device-loss-fanout.unit.test.ts +107 -0
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +21 -0
- package/src/__tests__/environment-generation.integration.test.ts +23 -0
- package/src/__tests__/expose-renderer-errors.unit.test.ts +34 -0
- package/src/__tests__/factory-contract.integration.test.ts +122 -7
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +4 -1
- package/src/__tests__/gpu-scene.unit.test.ts +38 -2
- package/src/__tests__/ibl/face-uniforms.unit.test.ts +2 -0
- package/src/__tests__/ibl-residency-publication.unit.test.ts +113 -0
- package/src/__tests__/instances-store.unit.test.ts +46 -0
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +29 -22
- package/src/__tests__/material-cooked-projection.unit.test.ts +19 -1
- package/src/__tests__/material-pass-policy.unit.test.ts +69 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +69 -0
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +29 -0
- package/src/__tests__/material-stride-surface.unit.test.ts +7 -3
- package/src/__tests__/material-surface-authoring.test-d.ts +62 -0
- package/src/__tests__/materials-standard-contract.unit.test.ts +104 -0
- package/src/__tests__/materials-transmission-validation.unit.test.ts +24 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -5
- package/src/__tests__/physical-clearcoat.integration.test.ts +89 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +1 -1
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +1 -1
- package/src/__tests__/recover-error-policy-owner.unit.test.ts +6 -3
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +140 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +127 -18
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +47 -0
- package/src/__tests__/renderer-generation-assembly.unit.test.ts +77 -0
- package/src/__tests__/renderer-generation-failure.unit.test.ts +108 -0
- package/src/__tests__/renderer-producer-root-matrix.integration.test.ts +33 -0
- package/src/__tests__/renderer-recovery-capability-matrix.unit.test.ts +59 -0
- package/src/__tests__/renderer-recovery-contract.unit.test.ts +73 -0
- package/src/__tests__/renderer-recovery-lifecycle.unit.test.ts +216 -0
- package/src/__tests__/renderer-target-history-recovery.integration.test.ts +80 -0
- package/src/__tests__/shader-manifest-fixture.ts +13 -16
- package/src/__tests__/shader-stage-surface.unit.test.ts +1 -1
- package/src/__tests__/skin-motion-regression.unit.test.ts +33 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +30 -2
- package/src/__tests__/standard-layer-projection.unit.test.ts +23 -0
- package/src/__tests__/surface-adjacent-regressions.integration.test.ts +60 -0
- package/src/__tests__/surface-standard-pipeline.browser.test.ts +20 -0
- package/src/__tests__/surface-standard-pipeline.dawn.test.ts +20 -0
- package/src/__tests__/surface-standard-pipeline.fixture.ts +132 -0
- package/src/__tests__/surface-variant-provenance.integration.test.ts +33 -0
- package/src/__tests__/transmission-prewarm.unit.test.ts +95 -85
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +1 -1
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +3 -1
- package/src/assembly/bundler-contract.ts +9 -0
- package/src/assembly/device-feature-admission.ts +15 -5
- package/src/assembly/extended-lighting-fallback.ts +216 -0
- package/src/assembly/factory.ts +83 -10088
- package/src/assembly/material/__tests__/standard-layer-plan-projection.integration.test.ts +18 -0
- package/src/assembly/material/__tests__/surface-pass-projection.integration.test.ts +62 -0
- package/src/assembly/material/assembly.ts +18 -2
- package/src/assembly/material/standard-layer-projection.ts +16 -0
- package/src/assembly/material/surface-projection.ts +90 -0
- package/src/assembly/material-shader-policy.ts +932 -0
- package/src/assembly/material-shader-prewarm.ts +88 -0
- package/src/assembly/mesh-ssbo-grow.ts +270 -0
- package/src/assembly/recovery/device-loss-fanout.ts +89 -0
- package/src/assembly/recovery/generation.ts +141 -0
- package/src/assembly/recovery/recovery-attempt.ts +800 -0
- package/src/assembly/recovery/renderer-recover.ts +906 -0
- package/src/assembly/renderer-facade.ts +342 -0
- package/src/assembly/renderer-frame-transaction.ts +45 -0
- package/src/assembly/renderer-helpers.ts +99 -0
- package/src/assembly/renderer-lifecycle.ts +159 -0
- package/src/assembly/shader-prewarm-policy.ts +157 -0
- package/src/assembly/webgpu-ready-contract.ts +14 -0
- package/src/assembly/webgpu-ready.ts +4066 -0
- package/src/assembly/webgpu-renderer.ts +4027 -0
- package/src/assembly/webgpu-vertex-layouts.ts +132 -0
- package/src/assets/asset-decoders.ts +27 -4
- package/src/components/camera.ts +1 -1
- package/src/components/instances.ts +14 -197
- package/src/debug-draw-glue.ts +1 -1
- package/src/device/device-scope.ts +35 -6
- package/src/device/gpu-residency.ts +194 -26
- package/src/environment/frame.ts +6 -0
- package/src/environment/inspection.ts +10 -0
- package/src/environment/lifecycle.ts +114 -8
- package/src/errors/recover.ts +76 -5
- package/src/errors/render.ts +17 -0
- package/src/extract/contracts.ts +974 -0
- package/src/features/host.ts +16 -0
- package/src/features/prepared-gpu-work.ts +20 -2
- package/src/features/prepared-graphics-store.ts +17 -0
- package/src/gpu-driven/production-raster.ts +131 -3
- package/src/gpu-scene.ts +87 -31
- package/src/ibl/IblPipelineCache.ts +134 -50
- package/src/ibl/skylight-bind-group.ts +26 -0
- package/src/index.ts +10 -1
- package/src/instance-buffer-cache.ts +14 -1
- package/src/instances.ts +288 -0
- package/src/light-buffer-layout.ts +3 -0
- package/src/materials.ts +365 -53
- package/src/mesh-material-bindings.ts +59 -0
- package/src/occlusion-proxy.ts +64 -0
- package/src/pbr-pipeline.ts +139 -15
- package/src/pipeline-builder.ts +14 -10
- package/src/pipeline-spec.ts +6 -14
- package/src/points-lines/__tests__/cache-recovery.unit.test.ts +22 -0
- package/src/points-lines/prepare.ts +9 -0
- package/src/points-lines/standard-owner.ts +403 -0
- package/src/record/__tests__/frame-targets-recovery.unit.test.ts +60 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +26 -1
- package/src/record/__tests__/mesh-ssbo.unit.test.ts +38 -0
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +124 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +28 -13
- package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +47 -4
- package/src/record/__tests__/temporal-payload.unit.test.ts +22 -43
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -1
- package/src/record/frame-snapshot.ts +34 -2
- package/src/record/frame-targets.ts +11 -1
- package/src/record/frame.ts +37 -4
- package/src/record/helpers.ts +1 -1
- package/src/record/main-pass-geometry.ts +727 -63
- package/src/record/main-pass-material.ts +316 -209
- package/src/record/main-pass-sprite-draws.ts +7 -8
- package/src/record/main-pass.ts +94 -6
- package/src/record/mesh-ssbo.ts +32 -10
- package/src/record/recovery-pipeline.ts +695 -0
- package/src/record/render-context.ts +39 -4
- package/src/record/shadow-pass.ts +46 -99
- package/src/record/typed-frame-graph.ts +45 -1
- package/src/record/view-ubo.ts +3 -3
- package/src/recovery/render-system-candidate.ts +876 -0
- package/src/render-contract.ts +69 -7
- package/src/render-system-extract-tail.ts +3039 -0
- package/src/render-system-extract.ts +177 -3003
- package/src/render-system.ts +906 -662
- package/src/scene/render-scene-types.ts +2 -0
- package/src/scene/render-scene.ts +703 -37
- package/src/systems/skin-palette-allocator.ts +129 -7
- package/src/temporal/frame-coordinator.ts +4 -1
- package/src/temporal/taa-history-store.ts +46 -2
- package/src/temporal/temporal-view.ts +1 -1
- package/src/temporal/transaction.ts +9 -0
- package/src/tilemap-chunk-extract-system.ts +1 -1
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +19 -12
- package/src/transmission/__tests__/surface-compatibility.integration.test.ts +32 -0
- package/dist/chunk-4L3P6DT5.mjs.map +0 -1
- package/dist/chunk-4NPUASZR.mjs +0 -203
- package/dist/chunk-4NPUASZR.mjs.map +0 -1
- package/dist/chunk-DIYW3M5D.mjs.map +0 -1
- package/dist/chunk-FBC4R44J.mjs.map +0 -1
- package/dist/chunk-FF7K3FSO.mjs.map +0 -1
- package/dist/chunk-HZUPSYW7.mjs.map +0 -1
- package/dist/chunk-QODA5UKU.mjs.map +0 -1
- package/dist/chunk-YALPS44A.mjs.map +0 -1
- package/dist/chunk-ZUWKAZ2I.mjs.map +0 -1
package/src/pbr-pipeline.ts
CHANGED
|
@@ -32,7 +32,11 @@ import type {
|
|
|
32
32
|
TextureFormat,
|
|
33
33
|
TextureView,
|
|
34
34
|
} from '@forgeax/engine-rhi';
|
|
35
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
type ShaderCatalog,
|
|
37
|
+
STANDARD_PIPELINE_PARAM_SCHEMA,
|
|
38
|
+
standardPhysicalTextureFields,
|
|
39
|
+
} from '@forgeax/engine-shader';
|
|
36
40
|
import { derive, type ParamSchemaEntry } from '@forgeax/engine-types';
|
|
37
41
|
import { GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX } from './gpu-stage';
|
|
38
42
|
import type { PipelineSpec } from './pipeline-spec-types';
|
|
@@ -101,11 +105,13 @@ export function standardPbrColorFormats(
|
|
|
101
105
|
/**
|
|
102
106
|
* The built-in standard-PBR material paramSchema's texture/user-region shape,
|
|
103
107
|
* used as the fallback when the material BGL is built without a registry
|
|
104
|
-
* (the caps-driven `buildPbrPipelineLayouts` seam). Declares the
|
|
105
|
-
* user-region textures + a numeric UBO run; `derive()` collapses the
|
|
106
|
-
* into binding 0 and emits sampler/texture
|
|
107
|
-
*
|
|
108
|
-
*
|
|
108
|
+
* (the caps-driven `buildPbrPipelineLayouts` seam). Declares the canonical
|
|
109
|
+
* Standard user-region textures + a numeric UBO run; `derive()` collapses the
|
|
110
|
+
* numerics into binding 0 and emits one sampler/texture pair per declared
|
|
111
|
+
* texture. Physical map pairs stay outside this boot region and are appended
|
|
112
|
+
* only for an authored root that declares them. The shared PBR parameter
|
|
113
|
+
* contract comes from the shader package; this module only derives the GPU
|
|
114
|
+
* layout.
|
|
109
115
|
*/
|
|
110
116
|
/**
|
|
111
117
|
* Build the PBR material BGL **user-region** from a paramSchema via the
|
|
@@ -116,9 +122,10 @@ export function standardPbrColorFormats(
|
|
|
116
122
|
* custom schema (e.g. parallax + heightTexture) shifts the injection region by
|
|
117
123
|
* one sampler/texture pair automatically.
|
|
118
124
|
*
|
|
119
|
-
* The
|
|
120
|
-
* so this derives to binding 0 UBO +
|
|
121
|
-
* after that
|
|
125
|
+
* The canonical `STANDARD_PIPELINE_PARAM_SCHEMA` currently declares seven
|
|
126
|
+
* non-physical textures, so this derives to binding 0 UBO + seven pairs = 15
|
|
127
|
+
* entries. IBL and transmission injection are appended after that region;
|
|
128
|
+
* authored physical maps are appended after the engine-owned injections.
|
|
122
129
|
*
|
|
123
130
|
* One material-UBO convention is layered on top of the pure `derive()` output:
|
|
124
131
|
* binding 0 is patched to `{ type: 'uniform', hasDynamicOffset: true }` with
|
|
@@ -132,9 +139,18 @@ export function standardPbrColorFormats(
|
|
|
132
139
|
* built-in standard-PBR shape when omitted, for the caps-driven seam).
|
|
133
140
|
*/
|
|
134
141
|
export function buildPbrMaterialUserRegionEntries(
|
|
135
|
-
paramSchema: readonly ParamSchemaEntry[] =
|
|
142
|
+
paramSchema: readonly ParamSchemaEntry[] = STANDARD_PIPELINE_PARAM_SCHEMA,
|
|
143
|
+
excludedTextureFields: readonly string[] = [],
|
|
136
144
|
): GPUBindGroupLayoutEntry[] {
|
|
137
|
-
const
|
|
145
|
+
const excluded = new Set(excludedTextureFields);
|
|
146
|
+
for (const field of standardPhysicalTextureFields(paramSchema)) excluded.add(field);
|
|
147
|
+
const derived = derive(
|
|
148
|
+
excluded.size === 0
|
|
149
|
+
? paramSchema
|
|
150
|
+
: paramSchema.filter(
|
|
151
|
+
(entry) => !excluded.has(entry.name) || !entry.type.startsWith('texture'),
|
|
152
|
+
),
|
|
153
|
+
);
|
|
138
154
|
// Project the engine-owned entry shape into the DOM WebGPU descriptor. Omit
|
|
139
155
|
// absent optional members so exactOptionalPropertyTypes remains true at the
|
|
140
156
|
// boundary instead of leaking an `undefined` property into the descriptor.
|
|
@@ -330,6 +346,68 @@ export const INJECTION_KIND_LENGTHS = {
|
|
|
330
346
|
transmission: TRANSMISSION_INJECTION_LENGTH,
|
|
331
347
|
};
|
|
332
348
|
|
|
349
|
+
export function physicalTextureFields(paramSchema: readonly ParamSchemaEntry[]): readonly string[] {
|
|
350
|
+
return standardPhysicalTextureFields(paramSchema);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export function appendTextureInjection(
|
|
354
|
+
bgl: readonly GPUBindGroupLayoutEntry[],
|
|
355
|
+
fields: readonly string[],
|
|
356
|
+
): GPUBindGroupLayoutEntry[] {
|
|
357
|
+
const start = bgl.length;
|
|
358
|
+
const fieldSet = new Set(fields);
|
|
359
|
+
return standardPhysicalTextureFields(
|
|
360
|
+
fields.map((name) => ({ name, type: 'texture2d' as const })),
|
|
361
|
+
).flatMap((field, index) => {
|
|
362
|
+
if (!fieldSet.has(field)) return [];
|
|
363
|
+
const binding = start + index * 2;
|
|
364
|
+
return [
|
|
365
|
+
{
|
|
366
|
+
binding,
|
|
367
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
368
|
+
sampler: { type: 'filtering' as const },
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
binding: binding + 1,
|
|
372
|
+
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
373
|
+
texture: { sampleType: 'float' as const, viewDimension: '2d' as const },
|
|
374
|
+
},
|
|
375
|
+
];
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Return the stable identity of the merged material bind-group layout.
|
|
381
|
+
*
|
|
382
|
+
* This is deliberately derived from the same descriptor builder consumed by
|
|
383
|
+
* the device path. Callers use it to keep pipeline, bind-group, and
|
|
384
|
+
* frame-local lookup caches on one layout identity even when equivalent
|
|
385
|
+
* paramSchema arrays were allocated independently.
|
|
386
|
+
*/
|
|
387
|
+
export function materialBindGroupLayoutIdentity(
|
|
388
|
+
shaderId: string,
|
|
389
|
+
paramSchema: readonly ParamSchemaEntry[],
|
|
390
|
+
): string {
|
|
391
|
+
const descriptor = buildBindGroupLayoutDescriptor(
|
|
392
|
+
{
|
|
393
|
+
shader: { id: shaderId, passKind: 'forward', variantSet: undefined },
|
|
394
|
+
attachments: { colorFormats: [], depthFormat: undefined, sampleCount: 1 },
|
|
395
|
+
geometry: { topology: 'triangle-list', vertexLayout: {} },
|
|
396
|
+
renderState: undefined,
|
|
397
|
+
},
|
|
398
|
+
{ kind: 'pbr-material-merged', materialParamSchema: paramSchema },
|
|
399
|
+
);
|
|
400
|
+
// Descriptor shape alone cannot distinguish two Standard roots that expose
|
|
401
|
+
// the same number of physical texture pairs under different semantic names.
|
|
402
|
+
// The resource order is part of the admitted root contract, so include the
|
|
403
|
+
// canonical physical projection in the cache identity while keeping the
|
|
404
|
+
// actual WebGPU descriptor owned by the builder above.
|
|
405
|
+
return JSON.stringify({
|
|
406
|
+
entries: descriptor.entries,
|
|
407
|
+
physicalTextureFields: physicalTextureFields(paramSchema),
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
|
|
333
411
|
/**
|
|
334
412
|
* Caps shape consumed by the BGL factory functions for storage-buffer vs
|
|
335
413
|
* uniform-buffer branching. Mirrors the two fields the engine reads from
|
|
@@ -568,7 +646,7 @@ export function buildPbrPipelineLayouts(
|
|
|
568
646
|
|
|
569
647
|
// Material BGL: derived user region + Skylight + transmission injection.
|
|
570
648
|
// The transmission start binding is computed from the post-Skylight BGL
|
|
571
|
-
// length (=
|
|
649
|
+
// length (= 22 for the canonical Standard schema) by appendInjection.
|
|
572
650
|
const materialBglRes = device.createBindGroupLayout(
|
|
573
651
|
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: 'pbr-material-merged' }),
|
|
574
652
|
);
|
|
@@ -658,6 +736,21 @@ export function buildPbrPipelineLayouts(
|
|
|
658
736
|
export const SKIN_MATERIAL_SHADER_ID = 'forgeax::pbr-skin' as const;
|
|
659
737
|
export const SHADOW_CASTER_SHADER_ID = 'forgeax::default-shadow-caster' as const;
|
|
660
738
|
|
|
739
|
+
// Authored Standard templates are published under a unique module id for each
|
|
740
|
+
// root contract. Keep the family marker in the id so every downstream render
|
|
741
|
+
// owner (extract, layout, and record) can make the same Standard-vs-custom and
|
|
742
|
+
// rigid-vs-skinned decision without a second registry or a runtime shader
|
|
743
|
+
// inspection pass.
|
|
744
|
+
const AUTHORED_STANDARD_ID_RE = /::(?:standard|pbr-skin)(?:-|$)/;
|
|
745
|
+
|
|
746
|
+
export function isStandardPbrSkinMaterialShader(shaderId: string | undefined): boolean {
|
|
747
|
+
return (
|
|
748
|
+
shaderId === SKIN_MATERIAL_SHADER_ID ||
|
|
749
|
+
shaderId === 'forgeax::default-standard-pbr-skin' ||
|
|
750
|
+
(shaderId !== undefined && /::pbr-skin(?:-|$)/.test(shaderId))
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
|
|
661
754
|
export function shadowCasterVariantSet(storageBuffer: boolean, skinned: boolean): string {
|
|
662
755
|
const skinningDisabled = !skinned;
|
|
663
756
|
if (storageBuffer && skinningDisabled) return '';
|
|
@@ -692,6 +785,22 @@ export function resolvePipelineGroup2Contract(source: string): PipelineGroup2Con
|
|
|
692
785
|
|
|
693
786
|
/** Returns true for the engine-shipped standard-PBR material shader family. */
|
|
694
787
|
export function isStandardPbrMaterialShader(shaderId: string | undefined): boolean {
|
|
788
|
+
return (
|
|
789
|
+
shaderId === 'forgeax::default-standard-pbr' ||
|
|
790
|
+
shaderId === SKIN_MATERIAL_SHADER_ID ||
|
|
791
|
+
shaderId === 'forgeax::default-standard-pbr-skin' ||
|
|
792
|
+
(shaderId !== undefined && AUTHORED_STANDARD_ID_RE.test(shaderId))
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* Return true only for the two engine-owned Standard roots. Authored Standard
|
|
798
|
+
* aliases intentionally remain outside this set: their cooked root schema may
|
|
799
|
+
* omit transmission or other optional resources, so their compact user-region
|
|
800
|
+
* layout must be derived from that artifact instead of borrowing the boot
|
|
801
|
+
* layout's reserved slots.
|
|
802
|
+
*/
|
|
803
|
+
export function isCanonicalStandardPbrMaterialShader(shaderId: string | undefined): boolean {
|
|
695
804
|
return (
|
|
696
805
|
shaderId === 'forgeax::default-standard-pbr' ||
|
|
697
806
|
shaderId === SKIN_MATERIAL_SHADER_ID ||
|
|
@@ -1240,14 +1349,29 @@ export function buildBindGroupLayoutDescriptor(
|
|
|
1240
1349
|
// + IBL injection (7) + transmission injection (2). The user-region
|
|
1241
1350
|
// size is the only variable; injection start = userRegion.length so a
|
|
1242
1351
|
// custom schema shifts IBL/transmission by its sampler/texture pairs.
|
|
1243
|
-
// The built-in
|
|
1352
|
+
// The built-in standard-PBR schema is 17 + 7 + 2 = 26 entries;
|
|
1353
|
+
// clearcoat texture pairs are derived from the effective root schema.
|
|
1244
1354
|
//
|
|
1245
1355
|
// Schema source priority (D-1): explicit materialParamSchema option >
|
|
1246
1356
|
// registry lookup of spec.shader.id > built-in standard-PBR fallback.
|
|
1247
1357
|
const resolvedSchema = resolveMaterialParamSchema(spec, options);
|
|
1248
|
-
const
|
|
1358
|
+
const effectiveSchema = resolvedSchema ?? STANDARD_PIPELINE_PARAM_SCHEMA;
|
|
1359
|
+
const physicalFields = physicalTextureFields(effectiveSchema);
|
|
1360
|
+
// Standard's built-in shader keeps the transmission user-region slots
|
|
1361
|
+
// reserved even when a particular root omits those values. Physical
|
|
1362
|
+
// maps extend that canonical region; they must not compact the IBL
|
|
1363
|
+
// bindings to the smaller authored subset. A compact user region is
|
|
1364
|
+
// still correct for authored (non-engine) material shaders.
|
|
1365
|
+
const userRegionSchema = isCanonicalStandardPbrMaterialShader(spec.shader.id)
|
|
1366
|
+
? STANDARD_PIPELINE_PARAM_SCHEMA
|
|
1367
|
+
: effectiveSchema;
|
|
1368
|
+
const userRegion = buildPbrMaterialUserRegionEntries(userRegionSchema);
|
|
1249
1369
|
const afterIbl = [...userRegion, ...appendInjection(userRegion, 'ibl')];
|
|
1250
|
-
const
|
|
1370
|
+
const afterTransmission = [...afterIbl, ...appendInjection(afterIbl, 'transmission')];
|
|
1371
|
+
const merged = [
|
|
1372
|
+
...afterTransmission,
|
|
1373
|
+
...appendTextureInjection(afterTransmission, physicalFields),
|
|
1374
|
+
];
|
|
1251
1375
|
return {
|
|
1252
1376
|
label: 'pbr-material-skylight-bgl',
|
|
1253
1377
|
entries: merged,
|
package/src/pipeline-builder.ts
CHANGED
|
@@ -277,7 +277,13 @@ export function buildPipelineForMaterialShader(
|
|
|
277
277
|
const vsEntry = vertexEntry ?? (passKind === 'temporal' ? 'vs_temporal' : 'vs_main');
|
|
278
278
|
const fsEntry =
|
|
279
279
|
fragmentEntry ??
|
|
280
|
-
(passKind === 'temporal'
|
|
280
|
+
(passKind === 'temporal'
|
|
281
|
+
? 'fs_temporal'
|
|
282
|
+
: passKind === 'deferred'
|
|
283
|
+
? 'fs_gbuffer'
|
|
284
|
+
: passKind === 'shadow-caster'
|
|
285
|
+
? 'fs_shadow'
|
|
286
|
+
: 'fs_main');
|
|
281
287
|
|
|
282
288
|
let source = entry.source;
|
|
283
289
|
if (defines !== undefined && Object.keys(defines).length > 0) {
|
|
@@ -345,15 +351,13 @@ export function buildPipelineForMaterialShader(
|
|
|
345
351
|
vertex: {
|
|
346
352
|
module: shaderModule,
|
|
347
353
|
entryPoint: vsEntry,
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
},
|
|
356
|
-
],
|
|
354
|
+
// Surface-backed Standard shadow entries evaluate the same material
|
|
355
|
+
// surface as Forward/Deferred, so their vertex stage consumes normal,
|
|
356
|
+
// UV, and tangent inputs in addition to position. Keep the complete
|
|
357
|
+
// derived mesh layout here; extra attributes remain legal for legacy
|
|
358
|
+
// position-only custom casters, while trimming to position would make
|
|
359
|
+
// the built-in Surface shadow shader fail WebGPU validation.
|
|
360
|
+
buffers: [...ctx.vertexBuffers],
|
|
357
361
|
},
|
|
358
362
|
// Vertex-only depth pass writes `fragment: undefined` (GPU derives
|
|
359
363
|
// depth from gl_Position.z). A custom ShadowCaster shader with a
|
package/src/pipeline-spec.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import {
|
|
21
21
|
deriveVertexBufferLayout,
|
|
22
|
+
deriveVertexBufferLayoutFromProjection,
|
|
22
23
|
deriveVertexLayoutProjection,
|
|
23
24
|
type VertexLayoutProjection,
|
|
24
25
|
} from '@forgeax/engine-geometry';
|
|
@@ -407,20 +408,11 @@ export function buildPipelineDescriptor(
|
|
|
407
408
|
? { shaderUvSetCount: geometry.shaderUvSetCount }
|
|
408
409
|
: {}),
|
|
409
410
|
})
|
|
410
|
-
: geometry.vertexLayoutProjection
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
{
|
|
414
|
-
|
|
415
|
-
attributes: geometry.vertexLayoutProjection.attributes.map(
|
|
416
|
-
({ shaderLocation, offset, format }) => ({
|
|
417
|
-
shaderLocation,
|
|
418
|
-
offset,
|
|
419
|
-
format,
|
|
420
|
-
}),
|
|
421
|
-
),
|
|
422
|
-
},
|
|
423
|
-
];
|
|
411
|
+
: deriveVertexBufferLayoutFromProjection(geometry.vertexLayoutProjection, {
|
|
412
|
+
...(geometry.shaderUvSetCount !== undefined
|
|
413
|
+
? { shaderUvSetCount: geometry.shaderUvSetCount }
|
|
414
|
+
: {}),
|
|
415
|
+
});
|
|
424
416
|
|
|
425
417
|
const descriptor: Record<string, unknown> = {
|
|
426
418
|
vertex: {
|
|
@@ -154,4 +154,26 @@ describe('Points/Lines expansion cache and LKG recovery', () => {
|
|
|
154
154
|
expect(preparation.prepare(snapshot(), mesh()).ok).toBe(true);
|
|
155
155
|
expect(preparation.inspect()).toMatchObject({ status: 'resident', lastKnownGood: true });
|
|
156
156
|
});
|
|
157
|
+
|
|
158
|
+
it('abandons lost-device handles without invoking the dead-device destroy path', () => {
|
|
159
|
+
let destroys = 0;
|
|
160
|
+
const preparation = new PointsLinesPreparation({
|
|
161
|
+
cache: new PointsLinesExpansionCache(),
|
|
162
|
+
adapter: {
|
|
163
|
+
create: () => ok('lost-device-resource'),
|
|
164
|
+
upload: () => ok(64),
|
|
165
|
+
validate: () => ok(undefined),
|
|
166
|
+
destroy: () => {
|
|
167
|
+
destroys += 1;
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
expect(preparation.prepare(snapshot(), mesh()).ok).toBe(true);
|
|
173
|
+
preparation.abandonForDeviceLoss();
|
|
174
|
+
preparation.abandonForDeviceLoss();
|
|
175
|
+
|
|
176
|
+
expect(destroys).toBe(0);
|
|
177
|
+
expect(preparation.inspect()).toMatchObject({ status: 'rebuild-pending', liveBytes: 0 });
|
|
178
|
+
});
|
|
157
179
|
});
|
|
@@ -37,6 +37,8 @@ export interface PointsLinesLanePreparationAdapter<Resource> {
|
|
|
37
37
|
mesh: MeshAsset,
|
|
38
38
|
): Result<PointsLinesPreparedResource<Resource>, PointsLinesPrepareFailedError>;
|
|
39
39
|
resetForDeviceLoss(): void;
|
|
40
|
+
/** Drop lost-device handles without calling destroy on the dead device. */
|
|
41
|
+
abandonForDeviceLoss(): void;
|
|
40
42
|
lastKnownGood(): PointsLinesPreparedResource<Resource> | undefined;
|
|
41
43
|
inspect(): PointsLinesPreparationInspection<Resource>;
|
|
42
44
|
}
|
|
@@ -121,6 +123,12 @@ export class PointsLinesPreparation<Resource> {
|
|
|
121
123
|
this.status = 'rebuild-pending';
|
|
122
124
|
}
|
|
123
125
|
|
|
126
|
+
abandonForDeviceLoss(): void {
|
|
127
|
+
this.live = undefined;
|
|
128
|
+
this.pendingCandidateBytes = 0;
|
|
129
|
+
this.status = 'rebuild-pending';
|
|
130
|
+
}
|
|
131
|
+
|
|
124
132
|
lastKnownGood(): PointsLinesPreparedResource<Resource> | undefined {
|
|
125
133
|
return this.live;
|
|
126
134
|
}
|
|
@@ -171,6 +179,7 @@ export function createPointsLinesLanePreparationAdapter<Resource>(
|
|
|
171
179
|
contract: createPointsLinesLaneContract(lane, backend),
|
|
172
180
|
prepare: (snapshot, mesh) => preparation.prepare(snapshot, mesh),
|
|
173
181
|
resetForDeviceLoss: () => preparation.resetForDeviceLoss(),
|
|
182
|
+
abandonForDeviceLoss: () => preparation.abandonForDeviceLoss(),
|
|
174
183
|
lastKnownGood: () => preparation.lastKnownGood(),
|
|
175
184
|
inspect: () => preparation.inspect(),
|
|
176
185
|
};
|