@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/instances.ts
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import type { World } from '@forgeax/engine-ecs';
|
|
2
|
+
import type { RhiErrorCode } from '@forgeax/engine-rhi';
|
|
3
|
+
|
|
4
|
+
const MATRIX_STRIDE = 16;
|
|
5
|
+
|
|
6
|
+
export type InstanceCollectionId = number & {
|
|
7
|
+
readonly __forgeaxInstanceCollectionId: unique symbol;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export interface InstanceCollectionInfo {
|
|
11
|
+
readonly collectionId: InstanceCollectionId;
|
|
12
|
+
readonly count: number;
|
|
13
|
+
readonly revision: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface InstanceUploadRange {
|
|
17
|
+
start: number;
|
|
18
|
+
end: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface InstanceCollectionSnapshot extends InstanceCollectionInfo {
|
|
22
|
+
readonly transforms: Float32Array;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** The renderer-owned submission lane selected for one collection. */
|
|
26
|
+
export type InstanceSubmissionLane =
|
|
27
|
+
| 'unresident'
|
|
28
|
+
| 'direct-storage'
|
|
29
|
+
| 'chunked-storage'
|
|
30
|
+
| 'direct-uniform'
|
|
31
|
+
| 'chunked-uniform'
|
|
32
|
+
| 'unavailable';
|
|
33
|
+
|
|
34
|
+
/** Backend identity carried by collection residency and failure facts. */
|
|
35
|
+
export type InstanceBackendKind = 'webgpu' | 'wgpu-native' | 'wgpu-webgl2' | 'null' | 'unknown';
|
|
36
|
+
|
|
37
|
+
/** Closed record-stage failure vocabulary for collection residency. */
|
|
38
|
+
export type InstanceCollectionFailureCode = RhiErrorCode | 'queue-write-buffer-failed';
|
|
39
|
+
|
|
40
|
+
/** Typed producer facts retained when a collection cannot be admitted. */
|
|
41
|
+
export interface InstanceCollectionFailureFacts {
|
|
42
|
+
readonly requestedBytes: number;
|
|
43
|
+
readonly supportedBytes: number | undefined;
|
|
44
|
+
readonly backend: InstanceBackendKind;
|
|
45
|
+
readonly owner: 'renderer.instances';
|
|
46
|
+
readonly cause: string;
|
|
47
|
+
readonly recovery: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Detached, bounded collection evidence exposed by Renderer.inspect(). */
|
|
51
|
+
export interface InstanceCollectionInspection extends InstanceCollectionInfo {
|
|
52
|
+
readonly residentGeneration: number | undefined;
|
|
53
|
+
readonly lane: InstanceSubmissionLane;
|
|
54
|
+
readonly uploadRanges: readonly InstanceUploadRange[];
|
|
55
|
+
readonly uploadedBytes: number;
|
|
56
|
+
readonly requestedBytes: number;
|
|
57
|
+
readonly supportedBytes: number | undefined;
|
|
58
|
+
readonly backend: InstanceBackendKind;
|
|
59
|
+
readonly owner: 'renderer.instances';
|
|
60
|
+
readonly error:
|
|
61
|
+
| {
|
|
62
|
+
readonly code: InstanceCollectionFailureCode;
|
|
63
|
+
readonly expected: string;
|
|
64
|
+
readonly hint: string;
|
|
65
|
+
readonly detail: InstanceCollectionFailureFacts;
|
|
66
|
+
}
|
|
67
|
+
| undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface InstanceResidency {
|
|
71
|
+
readonly frameNumber: number;
|
|
72
|
+
readonly residentGeneration: number | undefined;
|
|
73
|
+
readonly lane: InstanceSubmissionLane;
|
|
74
|
+
readonly uploadRanges: readonly InstanceUploadRange[];
|
|
75
|
+
readonly uploadedBytes: number;
|
|
76
|
+
readonly requestedBytes: number;
|
|
77
|
+
readonly supportedBytes: number | undefined;
|
|
78
|
+
readonly backend: InstanceBackendKind;
|
|
79
|
+
readonly error: InstanceCollectionInspection['error'];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function appendRange(ranges: InstanceUploadRange[], start: number, end: number): void {
|
|
83
|
+
if (start >= end) return;
|
|
84
|
+
// Updates are allowed to arrive in any order. Insert at the first range
|
|
85
|
+
// whose end reaches the new interval, then consume every range that starts
|
|
86
|
+
// before the merged end. This preserves the complete union for both
|
|
87
|
+
// adjacent and overlapping writes (for example [10, 12) then [8, 11)).
|
|
88
|
+
let index = 0;
|
|
89
|
+
while (index < ranges.length) {
|
|
90
|
+
const existing = ranges[index];
|
|
91
|
+
if (existing === undefined || existing.end >= start) break;
|
|
92
|
+
index += 1;
|
|
93
|
+
}
|
|
94
|
+
while (index < ranges.length) {
|
|
95
|
+
const existing = ranges[index];
|
|
96
|
+
if (existing === undefined || existing.start > end) break;
|
|
97
|
+
start = Math.min(start, existing.start);
|
|
98
|
+
end = Math.max(end, existing.end);
|
|
99
|
+
ranges.splice(index, 1);
|
|
100
|
+
}
|
|
101
|
+
ranges.splice(index, 0, { start, end });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
interface CollectionRecord extends InstanceCollectionInfo {
|
|
105
|
+
readonly world: World;
|
|
106
|
+
readonly entity: number;
|
|
107
|
+
readonly transforms: Float32Array;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Rebuildable per-renderer projection. World remains the authoring authority. */
|
|
111
|
+
export class InstanceProjectionStore {
|
|
112
|
+
private nextId = 1;
|
|
113
|
+
private identities = new WeakMap<World, Map<number, InstanceCollectionId>>();
|
|
114
|
+
private readonly records = new Map<InstanceCollectionId, CollectionRecord>();
|
|
115
|
+
|
|
116
|
+
project(world: World, entity: number, transforms: ArrayLike<number>): InstanceCollectionSnapshot {
|
|
117
|
+
let entities = this.identities.get(world);
|
|
118
|
+
if (entities === undefined) {
|
|
119
|
+
entities = new Map();
|
|
120
|
+
this.identities.set(world, entities);
|
|
121
|
+
}
|
|
122
|
+
let collectionId = entities.get(entity);
|
|
123
|
+
if (collectionId === undefined) {
|
|
124
|
+
collectionId = this.nextId++ as InstanceCollectionId;
|
|
125
|
+
entities.set(entity, collectionId);
|
|
126
|
+
}
|
|
127
|
+
const previous = this.records.get(collectionId);
|
|
128
|
+
const unchanged =
|
|
129
|
+
previous !== undefined &&
|
|
130
|
+
previous.transforms.length === transforms.length &&
|
|
131
|
+
previous.transforms.every((value, index) => Object.is(value, transforms[index]));
|
|
132
|
+
const record: CollectionRecord = unchanged
|
|
133
|
+
? previous
|
|
134
|
+
: {
|
|
135
|
+
collectionId,
|
|
136
|
+
world,
|
|
137
|
+
entity,
|
|
138
|
+
transforms: new Float32Array(transforms),
|
|
139
|
+
count: transforms.length / MATRIX_STRIDE,
|
|
140
|
+
revision: (previous?.revision ?? 0) + 1,
|
|
141
|
+
};
|
|
142
|
+
this.records.set(collectionId, record);
|
|
143
|
+
// Every consumer gets a complete snapshot. Reading never acknowledges an
|
|
144
|
+
// upload; each GPU resident records its own successfully uploaded revision.
|
|
145
|
+
return { ...this.info(record), transforms: record.transforms };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
retain(ids: ReadonlySet<InstanceCollectionId>): void {
|
|
149
|
+
for (const [id, record] of this.records) {
|
|
150
|
+
if (ids.has(id)) continue;
|
|
151
|
+
this.identities.get(record.world)?.delete(record.entity);
|
|
152
|
+
this.records.delete(id);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Release one producer-owned collection when its render identity is removed. */
|
|
157
|
+
release(world: World, entity: number): void {
|
|
158
|
+
const entities = this.identities.get(world);
|
|
159
|
+
const collectionId = entities?.get(entity);
|
|
160
|
+
if (collectionId === undefined) return;
|
|
161
|
+
entities?.delete(entity);
|
|
162
|
+
this.records.delete(collectionId);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
dispose(): void {
|
|
166
|
+
this.records.clear();
|
|
167
|
+
this.identities = new WeakMap();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Return detached residency facts for every live collection.
|
|
172
|
+
*
|
|
173
|
+
* @internal Joins CPU projection identity with the active device residency;
|
|
174
|
+
* callers only receive immutable PODs and never GPU handles.
|
|
175
|
+
*/
|
|
176
|
+
_inspections(
|
|
177
|
+
residency: ReadonlyMap<InstanceCollectionId, InstanceResidency> | undefined,
|
|
178
|
+
frameNumber: number,
|
|
179
|
+
): readonly InstanceCollectionInspection[] {
|
|
180
|
+
return Object.freeze(
|
|
181
|
+
[...this.records.values()].map((record) =>
|
|
182
|
+
this.projectInspection(record, residency?.get(record.collectionId), frameNumber),
|
|
183
|
+
),
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private info(record: CollectionRecord): InstanceCollectionInfo {
|
|
188
|
+
return Object.freeze({
|
|
189
|
+
collectionId: record.collectionId,
|
|
190
|
+
count: record.count,
|
|
191
|
+
revision: record.revision,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private projectInspection(
|
|
196
|
+
record: CollectionRecord,
|
|
197
|
+
residency: InstanceResidency | undefined,
|
|
198
|
+
frameNumber: number,
|
|
199
|
+
): InstanceCollectionInspection {
|
|
200
|
+
return Object.freeze({
|
|
201
|
+
...this.info(record),
|
|
202
|
+
residentGeneration: residency?.residentGeneration,
|
|
203
|
+
lane: residency?.lane ?? 'unresident',
|
|
204
|
+
uploadRanges: Object.freeze(
|
|
205
|
+
residency?.frameNumber === frameNumber
|
|
206
|
+
? residency.uploadRanges.map((range) => ({ ...range }))
|
|
207
|
+
: [],
|
|
208
|
+
),
|
|
209
|
+
uploadedBytes: residency?.frameNumber === frameNumber ? residency.uploadedBytes : 0,
|
|
210
|
+
requestedBytes: residency?.requestedBytes ?? record.count * MATRIX_STRIDE * 4,
|
|
211
|
+
supportedBytes: residency?.supportedBytes,
|
|
212
|
+
backend: residency?.backend ?? 'unknown',
|
|
213
|
+
owner: 'renderer.instances',
|
|
214
|
+
error: residency?.error,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** @internal Renderer record owner reports the accepted collection lane. */
|
|
220
|
+
export function recordInstanceResidency(
|
|
221
|
+
residency: Map<InstanceCollectionId, InstanceResidency>,
|
|
222
|
+
input: {
|
|
223
|
+
readonly collectionId: InstanceCollectionId;
|
|
224
|
+
readonly frameNumber: number;
|
|
225
|
+
readonly residentGeneration: number;
|
|
226
|
+
readonly lane: Exclude<InstanceSubmissionLane, 'unresident' | 'unavailable'>;
|
|
227
|
+
readonly uploadRanges: readonly InstanceUploadRange[];
|
|
228
|
+
readonly uploadedBytes: number;
|
|
229
|
+
readonly requestedBytes: number;
|
|
230
|
+
readonly supportedBytes: number | undefined;
|
|
231
|
+
readonly backend: InstanceBackendKind;
|
|
232
|
+
},
|
|
233
|
+
): void {
|
|
234
|
+
const previous = residency.get(input.collectionId);
|
|
235
|
+
const sameFrame =
|
|
236
|
+
previous !== undefined &&
|
|
237
|
+
previous.frameNumber === input.frameNumber &&
|
|
238
|
+
previous.error === undefined;
|
|
239
|
+
const uploadRanges = sameFrame
|
|
240
|
+
? [...previous.uploadRanges].reduce(
|
|
241
|
+
(ranges, range) => {
|
|
242
|
+
appendRange(ranges, range.start, range.end);
|
|
243
|
+
return ranges;
|
|
244
|
+
},
|
|
245
|
+
input.uploadRanges.map((range) => ({ ...range })),
|
|
246
|
+
)
|
|
247
|
+
: input.uploadRanges.map((range) => ({ ...range }));
|
|
248
|
+
residency.set(input.collectionId, {
|
|
249
|
+
frameNumber: input.frameNumber,
|
|
250
|
+
residentGeneration: input.residentGeneration,
|
|
251
|
+
lane: input.lane,
|
|
252
|
+
uploadRanges,
|
|
253
|
+
uploadedBytes: sameFrame ? previous.uploadedBytes + input.uploadedBytes : input.uploadedBytes,
|
|
254
|
+
requestedBytes: input.requestedBytes,
|
|
255
|
+
supportedBytes: input.supportedBytes,
|
|
256
|
+
backend: input.backend,
|
|
257
|
+
error: undefined,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** @internal Renderer record owner reports a typed admission failure. */
|
|
262
|
+
export function recordInstanceFailure(
|
|
263
|
+
residency: Map<InstanceCollectionId, InstanceResidency>,
|
|
264
|
+
input: {
|
|
265
|
+
readonly collectionId: InstanceCollectionId;
|
|
266
|
+
readonly code: InstanceCollectionFailureCode;
|
|
267
|
+
readonly expected: string;
|
|
268
|
+
readonly hint: string;
|
|
269
|
+
readonly facts: InstanceCollectionFailureFacts;
|
|
270
|
+
},
|
|
271
|
+
): void {
|
|
272
|
+
residency.set(input.collectionId, {
|
|
273
|
+
frameNumber: -1,
|
|
274
|
+
residentGeneration: undefined,
|
|
275
|
+
lane: 'unavailable',
|
|
276
|
+
uploadRanges: [],
|
|
277
|
+
uploadedBytes: 0,
|
|
278
|
+
requestedBytes: input.facts.requestedBytes,
|
|
279
|
+
supportedBytes: input.facts.supportedBytes,
|
|
280
|
+
backend: input.facts.backend,
|
|
281
|
+
error: {
|
|
282
|
+
code: input.code,
|
|
283
|
+
expected: input.expected,
|
|
284
|
+
hint: input.hint,
|
|
285
|
+
detail: { ...input.facts },
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
}
|
|
@@ -46,6 +46,9 @@ export const STORAGE_BUFFER_MIN_REQUIRED = 4;
|
|
|
46
46
|
|
|
47
47
|
/** Byte size of one Point/Spot/Rect DirectLightSlot. */
|
|
48
48
|
export const BYTES_PER_DIRECT_LIGHT_SLOT = 80;
|
|
49
|
+
/** std430 slot aliases retained for the WebGPU ready-state sizing table. */
|
|
50
|
+
export const POINT_LIGHT_STD430_BYTES = BYTES_PER_DIRECT_LIGHT_SLOT;
|
|
51
|
+
export const SPOT_LIGHT_STD430_BYTES = BYTES_PER_DIRECT_LIGHT_SLOT;
|
|
49
52
|
|
|
50
53
|
/**
|
|
51
54
|
* Cap gate at createRenderer time: check whether the device has enough
|